Skip to content

Commit

Permalink
feat(plugin-workspaces-export): support bundling as gzip based on fil…
Browse files Browse the repository at this point in the history
…e ext
  • Loading branch information
kherock committed Jun 20, 2021
1 parent 8b97c2c commit b24a50d
Show file tree
Hide file tree
Showing 17 changed files with 558 additions and 59 deletions.
293 changes: 272 additions & 21 deletions .pnp.js

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions packages/plugin-workspaces-export/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
"@yarnpkg/libzip": "^2.2.1",
"@yarnpkg/plugin-pack": "^2.2.1",
"clipanion": "^2.6.2",
"tar-stream": "^2.1.4",
"tslib": "^2.0.1"
},
"devDependencies": {
"@types/tar-stream": "^2.1.0",
"@yarnpkg/builder": "^2.1.2",
"@yarnpkg/plugin-pnp": "^2.3.1",
"typescript": "~4.0.3"
Expand Down
36 changes: 26 additions & 10 deletions packages/plugin-workspaces-export/sources/commands/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import {
ppath,
xfs,
} from "@yarnpkg/fslib";
import {getLibzipPromise} from '@yarnpkg/libzip';
import {packUtils} from "@yarnpkg/plugin-pack";
import {Command, Usage} from "clipanion";
import {getLibzipPromise} from '@yarnpkg/libzip';
import {packUtils} from "@yarnpkg/plugin-pack";
import {Command, Usage} from "clipanion";

import {genPackTgz, makeFetcher, makeResolver} from '../exportUtils';
import {genPackTgz, makeFetcher, makeGzipFromDirectory, makeResolver} from '../exportUtils';

// eslint-disable-next-line arca/no-default-export
export default class WorkspacesExportCommand extends BaseCommand {
Expand Down Expand Up @@ -189,12 +189,28 @@ export default class WorkspacesExportCommand extends BaseCommand {
});
await baseFs.removePromise(DEFAULT_LOCK_FILENAME);
await baseFs.removePromise(tmpConfiguration.get(`bstatePath`));

const libzip = await getLibzipPromise();
const zipFs = new ZipFS(target, {create: true, libzip});

await zipFs.copyPromise(PortablePath.root, PortablePath.dot, {baseFs, stableTime: true, stableSort: true});
await zipFs.saveAndClose();
// if (nodeLinker === `node-modules`)
// // node-modules linker doesn't need its cache folder
// await baseFs.removePromise(tmpConfiguration.get(`cacheFolder`));

if (target.endsWith(`.zip`)) {
report.reportJson({output: target, format: `zip`});
const libzip = await getLibzipPromise();
const zipFs = new ZipFS(target, {create: true, libzip});

await zipFs.copyPromise(PortablePath.root, PortablePath.dot, {baseFs, stableTime: true, stableSort: true});
await zipFs.saveAndClose();
} else {
const gzip = await makeGzipFromDirectory(tmpDir);
const write = xfs.createWriteStream(target);

gzip.pipe(write);

await new Promise(resolve => {
write.on(`finish`, resolve);
});
report.reportJson({output: target, format: `gzip`});
}

report.reportInfo(MessageName.UNNAMED, `Workspace exported to ${formatUtils.pretty(configuration, target, `magenta`)}`);
report.reportJson({output: target});
Expand Down
89 changes: 79 additions & 10 deletions packages/plugin-workspaces-export/sources/exportUtils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {MultiFetcher} from '@yarnpkg/core/lib/MultiFetcher';
import {MultiResolver} from '@yarnpkg/core/lib/MultiResolver';
import {ProtocolResolver} from '@yarnpkg/core/lib/ProtocolResolver';
import {VirtualResolver} from '@yarnpkg/core/lib/VirtualResolver';
import {Project, VirtualFetcher, Workspace, tgzUtils} from '@yarnpkg/core';
import {Filename, PortablePath, ppath, xfs, ZipCompression} from '@yarnpkg/fslib';
import {packUtils} from '@yarnpkg/plugin-pack';

import {WorkspacePackFetcher} from './WorkspacePackFetcher';
import {WorkspacePackResolver} from './WorkspacePackResolver';
import {MultiFetcher} from '@yarnpkg/core/lib/MultiFetcher';
import {MultiResolver} from '@yarnpkg/core/lib/MultiResolver';
import {ProtocolResolver} from '@yarnpkg/core/lib/ProtocolResolver';
import {VirtualResolver} from '@yarnpkg/core/lib/VirtualResolver';
import {Project, VirtualFetcher, Workspace, tgzUtils} from '@yarnpkg/core';
import {FakeFS, Filename, JailFS, PortablePath, ppath, xfs, ZipCompression} from '@yarnpkg/fslib';
import {packUtils} from '@yarnpkg/plugin-pack';
import tar from 'tar-stream';
import {createGzip} from 'zlib';

import {WorkspacePackFetcher} from './WorkspacePackFetcher';
import {WorkspacePackResolver} from './WorkspacePackResolver';

/**
* Make a MultiFetcher that resolves workspaces using WorkspacePackFetcher
Expand Down Expand Up @@ -84,3 +86,70 @@ export const genPackZip = async (workspace: Workspace, opts: {
return await tgzUtils.convertToZip(buffer, opts);
});
};

async function walk(cwdFs: FakeFS<PortablePath>) {
const list: Array<PortablePath> = [];

const cwdList: Array<PortablePath> = [PortablePath.root];

while (cwdList.length > 0) {
const cwd = cwdList.pop()!;
const stat = await cwdFs.lstatPromise(cwd);

if (stat.isDirectory()) {
const entries = await cwdFs.readdirPromise(cwd);

for (const entry of entries) {
cwdList.push(ppath.resolve(cwd, entry));
}
} else {
list.push(ppath.relative(PortablePath.root, cwd));
}
}

return list.sort();
}

export const makeGzipFromDirectory = async (directory: PortablePath) => {
const cwdFs = new JailFS(directory);
const files = await walk(cwdFs);
const pack = tar.pack();

process.nextTick(async () => {
for (const fileRequest of files) {
const file = ppath.normalize(fileRequest);

const stat = await cwdFs.lstatPromise(file);
const opts = {name: file, mtime: new Date(315532800000), mode: stat.mode};

let resolveFn: Function;
let rejectFn: Function;

const awaitTarget = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});

const cb = (error: any) => {
if (error) {
rejectFn(error);
} else {
resolveFn();
}
};

if (stat.isFile())
pack.entry({...opts, type: `file`}, await cwdFs.readFilePromise(file), cb);
else if (stat.isSymbolicLink())
pack.entry({...opts, type: `symlink`, linkname: await cwdFs.readlinkPromise(file)}, cb);

await awaitTarget;
}
pack.finalize();
});

const tgz = createGzip();
pack.pipe(tgz);

return tgz;
};
Loading

0 comments on commit b24a50d

Please sign in to comment.