Skip to content

Commit

Permalink
Fixed #7 (subdirectories)
Browse files Browse the repository at this point in the history
Added nested directory tests
  • Loading branch information
james-pre committed May 23, 2024
1 parent 614d260 commit a492147
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 29 deletions.
48 changes: 23 additions & 25 deletions src/ZipFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ export interface ZipOptions {
* This isn't that bad, so we might do this at a later date.
*/
export class ZipFS extends Readonly(Sync(FileSystem)) {
protected entries: Map<string, FileEntry> = new Map();
protected files: Map<string, FileEntry> = new Map();
protected directories: Map<string, string[]> = new Map();

protected _time = Date.now();

Expand Down Expand Up @@ -121,9 +122,20 @@ export class ZipFS extends Readonly(Sync(FileSystem)) {
}
// Strip the trailing '/' if it exists
const name = cd.name.endsWith('/') ? cd.name.slice(0, -1) : cd.name;
this.entries.set('/' + name, cd);
this.files.set('/' + name, cd);
ptr += cd.size;
}

// Parse directories
for (const entry of this.files.keys()) {
const { dir, base } = parse(entry);

if (!this.directories.has(dir)) {
this.directories.set(dir, []);
}

this.directories.get(dir).push(base);
}
}

public metadata(): FileSystemMetadata {
Expand All @@ -136,29 +148,27 @@ export class ZipFS extends Readonly(Sync(FileSystem)) {
}

public get numberOfCentralDirectoryEntries(): number {
return this.entries.size;
return this.files.size;
}

public statSync(path: string): Stats {
// The EOCD/Header does not track '/', so it does not exist in `entries`
if (path == '/') {
// The EOCD/Header does not track directories, so it does not exist in `entries`
if (this.directories.has(path)) {
return new Stats({
mode: 0o555 | FileType.DIRECTORY,
size: [...this.entries.values()].reduce((size, entry) => size + entry.uncompressedSize, 0),
size: 4096,
mtimeMs: this._time,
ctimeMs: this._time,
atimeMs: Date.now(),
birthtimeMs: this._time,
});
}

const entry = this.entries.get(path);

if (!entry) {
throw ErrnoError.With('ENOENT', path, 'stat');
if (this.files.has(path)) {
return this.files.get(path).stats;
}

return entry.stats;
throw ErrnoError.With('ENOENT', path, 'stat');
}

public openFileSync(path: string, flag: string, cred: Cred): NoSyncFile<this> {
Expand All @@ -173,19 +183,7 @@ export class ZipFS extends Readonly(Sync(FileSystem)) {
throw ErrnoError.With('EACCES', path, 'openFile');
}

return new NoSyncFile(this, path, flag, stats, stats.isDirectory() ? stats.fileData : this.entries.get(path).data);
}

protected dirEntries(path: string): string[] {
const entries = [];

for (const entry of this.entries.keys()) {
const { dir, base } = parse(entry);
if (path == dir) {
entries.push(base);
}
}
return entries;
return new NoSyncFile(this, path, flag, stats, stats.isDirectory() ? stats.fileData : this.files.get(path).data);
}

public readdirSync(path: string): string[] {
Expand All @@ -195,7 +193,7 @@ export class ZipFS extends Readonly(Sync(FileSystem)) {
throw ErrnoError.With('ENOTDIR', path, 'readdir');
}

return this.dirEntries(path);
return this.directories.get(path);
}
}

Expand Down
Binary file modified tests/data.zip
Binary file not shown.
16 changes: 12 additions & 4 deletions tests/zip.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Zip } from '../dist/ZipFS.js';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

describe('Basic zip file', () => {
describe('Basic ZIP operations', () => {
test('Configure', async () => {
const buffer = readFileSync(dirname(fileURLToPath(import.meta.url)) + '/data.zip');
const data = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
Expand All @@ -17,14 +17,22 @@ describe('Basic zip file', () => {
});

test('readdir /', () => {
expect(fs.readdirSync('/').length).toBe(2);
expect(fs.readdirSync('/').length).toBe(3);
});

test('read #1', () => {
test('read /one.txt', () => {
expect(fs.readFileSync('/one.txt', 'utf8')).toBe('1');
});

test('read #2', () => {
test('read /two.txt', () => {
expect(fs.readFileSync('/two.txt', 'utf8')).toBe('two');
});

test('readdir /nested', () => {
expect(fs.readdirSync('/nested').length).toBe(1);
});

test('readdir /nested/omg.txt', () => {
expect(fs.readFileSync('/nested/omg.txt', 'utf8')).toBe('This is a nested file!');
});
});

0 comments on commit a492147

Please sign in to comment.