Skip to content

Commit 9e9f3a0

Browse files
committed
Tests passing
1 parent 6450ddf commit 9e9f3a0

File tree

4 files changed

+57
-84
lines changed

4 files changed

+57
-84
lines changed

src/consts.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ export const VAL_TOWN_PROJECT_URL_REGEX =
5151

5252
export type ProjectItemType = typeof ProjectItems[number];
5353
export type ProjectFileType = Exclude<ProjectItemType, "directory">;
54+
55+
export const RECENT_VERSION_COUNT = 5;

src/vt/lib/clone.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ export function clone({
3535
version,
3636
branch_id: branchId,
3737
path: "",
38+
recursive: true,
3839
});
3940

4041
await Promise.all(projectItems
42+
.filter(file => !shouldIgnore(file.path, gitignoreRules))
4143
.map(async (file) => {
42-
// Skip ignored files
43-
if (shouldIgnore(file.path, gitignoreRules)) return;
44-
4544
if (file.type === "directory") {
4645
// Create directories, even if they would otherwise get created during
4746
// the createFile call later, so that we get empty directories

src/vt/lib/paths.ts

Lines changed: 34 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { DEFAULT_VAL_TYPE, type ProjectItemType } from "~/consts.ts";
1+
import {
2+
DEFAULT_VAL_TYPE,
3+
type ProjectItemType,
4+
RECENT_VERSION_COUNT,
5+
} from "~/consts.ts";
26
import { filePathToFile } from "~/sdk.ts";
37
import { compile as compileGitignore } from "gitignore-parser";
48

@@ -27,67 +31,41 @@ async function getProjectItemType(
2731
version: number,
2832
filePath: string,
2933
): Promise<ProjectItemType> {
30-
try {
31-
// Try up to 5 previous versions to determine the type
32-
for (let i = 0; i < 5; i++) {
33-
try {
34-
// Try to get the file at the current version min, ensuring version
35-
// doesn't go below 1
36-
const versionToCheck = Math.max(1, version - i);
37-
const result = await filePathToFile(
38-
projectId,
39-
branchId,
40-
versionToCheck,
41-
filePath,
42-
)
43-
.then((resp) => resp.type);
44-
return result;
45-
} catch (e) {
46-
// If not found and we haven't tried all versions yet, continue to the
47-
// next version
48-
if (e instanceof Deno.errors.NotFound && i < 4) {
49-
continue;
50-
} else if (!(e instanceof Deno.errors.NotFound) || i >= 4) {
51-
// If it's not a NotFound error or we've tried all versions, handle
52-
// it in the outer catch
53-
throw e;
54-
}
55-
}
34+
for (let i = version; i > version - RECENT_VERSION_COUNT; i--) {
35+
try {
36+
return await filePathToFile(projectId, branchId, version, filePath)
37+
.then((resp) => resp.type);
38+
} catch (e) {
39+
if (e instanceof Deno.errors.NotFound) {
40+
continue;
41+
} else throw e;
5642
}
43+
}
5744

58-
// If we get here, we couldn't find the file in any of the 5 versions
59-
throw new Deno.errors.NotFound();
60-
} catch (e) {
61-
// Otherwise, if it ends in .ts, .js, .tsx, or .jsx, it is a val
62-
if (e instanceof Deno.errors.NotFound) {
63-
if (/\.(ts|tsx|js|jsx)$/.test(filePath)) {
64-
const isCron = filePath.includes("cron");
65-
const isHttp = filePath.includes("http");
66-
const isEmail = filePath.includes("email");
67-
68-
// If it's ambiguous then it is a script val by default
69-
if ([isCron, isHttp, isEmail].filter(Boolean).length > 1) {
70-
return DEFAULT_VAL_TYPE;
71-
}
45+
// Otherwise, if it ends in .ts, .js, .tsx, or .jsx, it is a val
46+
if (/\.(ts|tsx|js|jsx)$/.test(filePath)) {
47+
const isCron = filePath.includes("cron");
48+
const isHttp = filePath.includes("http");
49+
const isEmail = filePath.includes("email");
7250

73-
// But otherwise look at the file name and try to figure out what type
74-
// of val it is based on whether the file name contains a pattern like
75-
// "cron," etc
76-
if (isCron) return "interval";
77-
if (isHttp) return "http";
78-
if (isEmail) return "email";
51+
// If it's ambiguous then it is a script val by default
52+
if ([isCron, isHttp, isEmail].filter(Boolean).length > 1) {
53+
return DEFAULT_VAL_TYPE;
54+
}
7955

80-
// If we can't figure it out, default to script
81-
return DEFAULT_VAL_TYPE;
82-
}
56+
// But otherwise look at the file name and try to figure out what type
57+
// of val it is based on whether the file name contains a pattern like
58+
// "cron," etc
59+
if (isCron) return "interval";
60+
if (isHttp) return "http";
61+
if (isEmail) return "email";
8362

84-
// Otherwise, it's just a plain old file val
85-
return "file";
86-
} else {
87-
// Re-throw any other errors
88-
throw e;
89-
}
63+
// If we can't figure it out, default to script
64+
return DEFAULT_VAL_TYPE;
9065
}
66+
67+
// Otherwise, it's just a plain old file val
68+
return "file";
9169
}
9270

9371
/**

src/vt/lib/push.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,28 +45,31 @@ export async function push({
4545
});
4646

4747
// Upload files that were modified locally
48-
const modifiedPromises = statusResult.modified
49-
.filter((file) => file.type !== "directory")
50-
.map(async (file) => {
51-
await sdk.projects.files.update(
52-
projectId,
53-
{
54-
path: file.path,
55-
branch_id: branchId,
56-
content: await Deno.readTextFile(path.join(targetDir, file.path)),
57-
name: path.basename(file.path),
58-
type: file.type as Exclude<ProjectItemType, "directory">,
59-
},
60-
);
61-
});
48+
await Promise.all(
49+
statusResult.modified
50+
.filter((file) => file.type !== "directory")
51+
.map(async (file) => {
52+
await sdk.projects.files.update(
53+
projectId,
54+
{
55+
path: file.path,
56+
branch_id: branchId,
57+
content: await Deno.readTextFile(path.join(targetDir, file.path)),
58+
name: path.basename(file.path),
59+
type: file.type as Exclude<ProjectItemType, "directory">,
60+
},
61+
);
62+
}),
63+
);
6264

6365
// Delete files that exist on the server but not locally
64-
const deletedPromises = statusResult.deleted.map(async (file) => {
66+
await Promise.all(statusResult.deleted.map(async (file) => {
6567
await sdk.projects.files.delete(projectId, {
6668
path: file.path,
6769
branch_id: branchId,
70+
recursive: true,
6871
});
69-
});
72+
}));
7073

7174
// First ensure all directories exist
7275
for (const file of statusResult.created) {
@@ -98,12 +101,6 @@ export async function push({
98101
}
99102
}
100103

101-
// Wait for all operations to complete
102-
await Promise.all([
103-
...modifiedPromises,
104-
...deletedPromises,
105-
]);
106-
107104
return statusResult;
108105
}
109106

@@ -116,9 +113,6 @@ async function ensureValtownDir(
116113
// Note that we cannot use path logic here because it must specific to val town
117114
const dirPath = isDirectory ? filePath : path.dirname(filePath);
118115

119-
// If path is "." (current directory) or empty, no directories need to be created
120-
if (dirPath === "." || dirPath === "") return;
121-
122116
// Split the path into segments
123117
const segments = dirPath.split("/");
124118
let currentPath = "";

0 commit comments

Comments
 (0)