Skip to content

Commit 2c30919

Browse files
refactor(site): Remove untar dep and support nested folders on template version page (#6244)
1 parent 8360357 commit 2c30919

File tree

11 files changed

+95
-132
lines changed

11 files changed

+95
-132
lines changed

site/js-untar.d.ts

-23
This file was deleted.

site/package.json

-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
"history": "5.3.0",
6060
"i18next": "21.9.1",
6161
"jest-location-mock": "1.0.9",
62-
"js-untar": "2.0.0",
6362
"just-debounce-it": "3.1.1",
6463
"lodash": "4.17.21",
6564
"playwright": "^1.29.2",
@@ -103,7 +102,6 @@
103102
"@types/react-helmet": "6.1.5",
104103
"@types/react-syntax-highlighter": "15.5.5",
105104
"@types/semver": "7.3.12",
106-
"@types/tar-js": "^0.3.2",
107105
"@types/ua-parser-js": "0.7.36",
108106
"@types/uuid": "8.3.4",
109107
"@typescript-eslint/eslint-plugin": "5.50.0",

site/site.go

-2
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,6 @@ func cspHeaders(next http.Handler) http.Handler {
326326
// Report all violations back to the server to log
327327
CSPDirectiveReportURI: {"/api/v2/csp/reports"},
328328
CSPFrameAncestors: {"'none'"},
329-
// worker for loading the .tar files on FE using js-untar
330-
CSPDirectiveWorkerSrc: {"'self' blob:"},
331329

332330
// Only scripts can manipulate the dom. This prevents someone from
333331
// naming themselves something like '<svg onload="alert(/cross-site-scripting/)" />'.

site/src/pages/TemplateVersionPage/TemplateVersionEditorPage/TemplateVersionEditorPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const TemplateVersionEditorPage: FC = () => {
2727
},
2828
{
2929
onSuccess(data) {
30-
sendEvent({ type: "INITIALIZE", untarFiles: data.untarFiles })
30+
sendEvent({ type: "INITIALIZE", tarReader: data.tarReader })
3131
},
3232
},
3333
)

site/src/pages/TemplateVersionPage/TemplateVersionEditorPage/data.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useQuery, UseQueryOptions } from "@tanstack/react-query"
22
import { getFile, getTemplateByName, getTemplateVersionByName } from "api/api"
3+
import { TarReader } from "util/tar"
34
import { createTemplateVersionFileTree } from "util/templateVersion"
4-
import untar, { File as UntarFile } from "js-untar"
55

66
const getTemplateVersionData = async (
77
orgId: string,
@@ -13,17 +13,15 @@ const getTemplateVersionData = async (
1313
getTemplateVersionByName(orgId, templateName, versionName),
1414
])
1515
const tarFile = await getFile(version.job.file_id)
16-
let untarFiles: UntarFile[] = []
17-
await untar(tarFile).then((files) => {
18-
untarFiles = files
19-
})
20-
const fileTree = await createTemplateVersionFileTree(untarFiles)
16+
const tarReader = new TarReader()
17+
await tarReader.readFile(tarFile)
18+
const fileTree = await createTemplateVersionFileTree(tarReader)
2119

2220
return {
2321
template,
2422
version,
2523
fileTree,
26-
untarFiles,
24+
tarReader,
2725
}
2826
}
2927

site/src/util/tar.test.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ test("tar", async () => {
99
writer.addFile("b.txt", new Blob(["world"]), { mtime })
1010
writer.addFile("c.txt", "", { mtime })
1111
writer.addFolder("etc", { mtime })
12-
writer.addFile("etc/d.txt", "", { mtime })
12+
writer.addFile("etc/d.txt", "Some text content", {
13+
mtime,
14+
user: "coder",
15+
group: "codergroup",
16+
mode: parseInt("777", 8),
17+
})
1318
const blob = await writer.write()
1419

1520
// Read
@@ -32,8 +37,11 @@ test("tar", async () => {
3237
})
3338
verifyFile(fileInfos[4], reader.getTextFile(fileInfos[4].name) as string, {
3439
name: "etc/d.txt",
35-
content: "",
40+
content: "Some text content",
3641
})
42+
expect(fileInfos[4].group).toEqual("codergroup")
43+
expect(fileInfos[4].user).toEqual("coder")
44+
expect(fileInfos[4].mode).toEqual(parseInt("777", 8))
3745
})
3846

3947
function verifyFile(

site/src/util/tar.ts

+35-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export interface ITarFileInfo {
1313
name: string
1414
type: TarFileType
1515
size: number
16+
mode: number
17+
mtime: number
18+
user: string
19+
group: string
1620
headerOffset: number
1721
}
1822

@@ -34,7 +38,7 @@ export interface ITarWriteOptions {
3438
}
3539

3640
export class TarReader {
37-
private fileInfo: ITarFileInfo[] = []
41+
public fileInfo: ITarFileInfo[] = []
3842
private _buffer: ArrayBuffer | null = null
3943

4044
constructor() {
@@ -64,22 +68,28 @@ export class TarReader {
6468
private readFileInfo() {
6569
this.fileInfo = []
6670
let offset = 0
67-
let fileSize = 0
68-
let fileName = ""
69-
let fileType: TarFileType
71+
7072
while (offset < this.buffer.byteLength - 512) {
71-
fileName = this.readFileName(offset)
73+
const fileName = this.readFileName(offset)
7274
if (!fileName) {
7375
break
7476
}
75-
fileType = this.readFileType(offset)
76-
fileSize = this.readFileSize(offset)
77+
const fileType = this.readFileType(offset)
78+
const fileSize = this.readFileSize(offset)
79+
const fileMode = this.readFileMode(offset)
80+
const fileMtime = this.readFileMtime(offset)
81+
const fileUser = this.readFileUser(offset)
82+
const fileGroup = this.readFileGroup(offset)
7783

7884
this.fileInfo.push({
7985
name: fileName,
8086
type: fileType,
8187
size: fileSize,
8288
headerOffset: offset,
89+
mode: fileMode,
90+
mtime: fileMtime,
91+
user: fileUser,
92+
group: fileGroup,
8393
})
8494

8595
offset += 512 + 512 * Math.floor((fileSize + 511) / 512)
@@ -100,6 +110,24 @@ export class TarReader {
100110
return this.readString(offset, 100)
101111
}
102112

113+
private readFileMode(offset: number) {
114+
const mode = this.readString(offset + 100, 8)
115+
return parseInt(mode, 8)
116+
}
117+
118+
private readFileMtime(offset: number) {
119+
const mtime = this.readString(offset + 136, 12)
120+
return parseInt(mtime, 8)
121+
}
122+
123+
private readFileUser(offset: number) {
124+
return this.readString(offset + 265, 32)
125+
}
126+
127+
private readFileGroup(offset: number) {
128+
return this.readString(offset + 297, 32)
129+
}
130+
103131
private readFileType(offset: number) {
104132
const typeView = new Uint8Array(this.buffer, offset + 156, 1)
105133
const typeStr = String.fromCharCode(typeView[0])

site/src/util/templateVersion.ts

+15-37
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as API from "api/api"
22
import { TemplateVersion } from "api/typesGenerated"
3-
import untar, { File as UntarFile } from "js-untar"
43
import { FileTree, setFile } from "./filetree"
4+
import { TarReader } from "./tar"
55

66
/**
77
* Content by filename
@@ -10,32 +10,16 @@ export type TemplateVersionFiles = Record<string, string>
1010

1111
export const getTemplateVersionFiles = async (
1212
version: TemplateVersion,
13-
allowedExtensions: string[],
14-
allowedFiles: string[],
1513
): Promise<TemplateVersionFiles> => {
1614
const files: TemplateVersionFiles = {}
1715
const tarFile = await API.getFile(version.job.file_id)
18-
const blobs: Record<string, Blob> = {}
19-
20-
await untar(tarFile).then(undefined, undefined, async (file) => {
21-
const paths = file.name.split("/")
22-
const filename = paths[paths.length - 1]
23-
const [_, extension] = filename.split(".")
24-
25-
if (
26-
allowedExtensions.includes(extension) ||
27-
allowedFiles.includes(filename)
28-
) {
29-
blobs[filename] = file.blob
16+
const tarReader = new TarReader()
17+
await tarReader.readFile(tarFile)
18+
for (const file of tarReader.fileInfo) {
19+
if (isAllowedFile(file.name)) {
20+
files[file.name] = tarReader.getTextFile(file.name) as string
3021
}
31-
})
32-
33-
await Promise.all(
34-
Object.entries(blobs).map(async ([filename, blob]) => {
35-
files[filename] = await blob.text()
36-
}),
37-
)
38-
22+
}
3923
return files
4024
}
4125

@@ -46,23 +30,17 @@ export const isAllowedFile = (name: string) => {
4630
}
4731

4832
export const createTemplateVersionFileTree = async (
49-
untarFiles: UntarFile[],
33+
tarReader: TarReader,
5034
): Promise<FileTree> => {
5135
let fileTree: FileTree = {}
52-
const blobs: Record<string, Blob> = {}
53-
54-
for (const untarFile of untarFiles) {
55-
if (isAllowedFile(untarFile.name)) {
56-
blobs[untarFile.name] = untarFile.blob
36+
for (const file of tarReader.fileInfo) {
37+
if (isAllowedFile(file.name)) {
38+
fileTree = setFile(
39+
file.name,
40+
tarReader.getTextFile(file.name) as string,
41+
fileTree,
42+
)
5743
}
5844
}
59-
60-
await Promise.all(
61-
Object.entries(blobs).map(async ([fullPath, blob]) => {
62-
const content = await blob.text()
63-
fileTree = setFile(fullPath, content, fileTree)
64-
}),
65-
)
66-
6745
return fileTree
6846
}

site/src/xServices/templateVersion/templateVersionXService.ts

+2-16
Original file line numberDiff line numberDiff line change
@@ -162,23 +162,9 @@ export const templateVersionMachine = createMachine(
162162
}
163163
const loadFilesPromises: ReturnType<typeof getTemplateVersionFiles>[] =
164164
[]
165-
const allowedExtensions = ["tf", "md"]
166-
const allowedFiles = ["Dockerfile"]
167-
loadFilesPromises.push(
168-
getTemplateVersionFiles(
169-
currentVersion,
170-
allowedExtensions,
171-
allowedFiles,
172-
),
173-
)
165+
loadFilesPromises.push(getTemplateVersionFiles(currentVersion))
174166
if (previousVersion) {
175-
loadFilesPromises.push(
176-
getTemplateVersionFiles(
177-
previousVersion,
178-
allowedExtensions,
179-
allowedFiles,
180-
),
181-
)
167+
loadFilesPromises.push(getTemplateVersionFiles(previousVersion))
182168
}
183169
const [currentFiles, previousFiles] = await Promise.all(
184170
loadFilesPromises,

0 commit comments

Comments
 (0)