Skip to content

Commit

Permalink
chore: fixed up header type mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
aryanjassal committed Feb 12, 2025
1 parent f10e844 commit d706025
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 30 deletions.
22 changes: 6 additions & 16 deletions src/Generator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { TarType, DirectoryContent } from './types';
import fs from 'fs';
import path from 'path';
import { TarTypes } from './types';
import * as errors from './errors';

/**
Expand All @@ -23,7 +24,7 @@ function createHeader(filePath: string, stat: fs.Stats, type: TarType): Buffer {
);
}

const size = type === '0' ? stat.size : 0;
const size = type === TarTypes.FILE ? stat.size : 0;
const header = Buffer.alloc(BLOCK_SIZE, 0);

// The TAR headers follow this structure
Expand All @@ -47,7 +48,6 @@ function createHeader(filePath: string, stat: fs.Stats, type: TarType): Buffer {
// 345 155 File name (last 155 bytes, total 255 bytes, null-padded)
// 500 12 '\0' (unused)

// FIXME: Assuming file path is under 100 characters long
header.write(filePath.slice(0, 99).padEnd(100, '\0'), 0, 100, 'utf8');
header.write(stat.mode.toString(8).padStart(7, '0') + '\0', 100, 12, 'ascii');
header.write(stat.uid.toString(8).padStart(7, '0') + '\0', 108, 12, 'ascii');
Expand Down Expand Up @@ -109,10 +109,10 @@ async function* walkDirectory(
const tarPath = path.join(relativePath, entry);

if (stat.isDirectory()) {
yield { path: tarPath + '/', stat: stat, type: '5' };
yield { path: tarPath + '/', stat: stat, type: TarTypes.DIRECTORY };
yield* walkDirectory(baseDir, path.join(relativePath, entry));
} else if (stat.isFile()) {
yield { path: tarPath, stat: stat, type: '0' };
yield { path: tarPath, stat: stat, type: TarTypes.FILE };
}
}
}
Expand All @@ -122,7 +122,7 @@ async function* createTar(baseDir: string): AsyncGenerator<Buffer, void, void> {
// Create header
yield createHeader(entry.path, entry.stat, entry.type);

if (entry.type === '0') {
if (entry.type === TarTypes.FILE) {
// Get file contents
yield* readFile(path.join(baseDir, entry.path));
}
Expand All @@ -133,14 +133,4 @@ async function* createTar(baseDir: string): AsyncGenerator<Buffer, void, void> {
yield Buffer.alloc(BLOCK_SIZE, 0);
}

// NOTE: probably need to remove this, idk
// this is a library and should only worry about tarring itself and not writing to fs
async function writeArchive(inputFile: string, outputFile: string) {
const fileHandle = await fs.promises.open(outputFile, 'w+');
for await (const chunk of createTar(inputFile)) {
await fileHandle.write(chunk);
}
await fileHandle.close();
}

export { createHeader, readFile, createTar, writeArchive };
export { createHeader, readFile, createTar };
16 changes: 7 additions & 9 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import type { Stats } from 'fs';

// FIXME: Using 0s and 5s for files and directories isn't a good way to handle
// this. I need to make it simpler so that I can assign and test using strings.
// A potential solution is enums, but they don't work with types, so it's a bit
// weird.
type TarFile = '0';
const TarTypes = {
FILE: '0',
DIRECTORY: '5',
} as const;

type TarDirectory = '5';

type TarType = TarFile | TarDirectory;
type TarType = (typeof TarTypes)[keyof typeof TarTypes];

type DirectoryContent = {
path: string;
stat: Stats;
type: TarType;
};

export type { TarFile, TarDirectory, TarType, DirectoryContent };
export type { TarType, DirectoryContent };
export { TarTypes };
25 changes: 20 additions & 5 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import { writeArchive } from '@/Generator';
import fs from 'fs';
import { createTar } from '@/Generator';

// TODO: actually write tests
describe('index', () => {
test.skip('test', async () => {
await expect(
writeArchive('/home/aryanj/Downloads', '/home/aryanj/archive.tar'),
).toResolve();
test('test', async () => {
if (process.env['CI'] != null) {
// Skip this test if on CI
expect(true).toEqual(true);
} else {
// Otherwise, run the test which creates a test archive
const writeArchive = async (inputFile: string, outputFile: string) => {
const fileHandle = await fs.promises.open(outputFile, 'w+');
for await (const chunk of createTar(inputFile)) {
await fileHandle.write(chunk);
}
await fileHandle.close();
};
await expect(
writeArchive('/home/aryanj/Downloads', '/home/aryanj/archive.tar'),
).toResolve();
}
}, 60000);
});

0 comments on commit d706025

Please sign in to comment.