Skip to content

Commit

Permalink
Add new sync implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
scott-rc committed Dec 5, 2023
1 parent 22e5bd9 commit 5bac25e
Show file tree
Hide file tree
Showing 9 changed files with 1,148 additions and 16 deletions.
88 changes: 83 additions & 5 deletions spec/__support__/filesync.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import fs from "fs-extra";
import assert from "node:assert";
import os from "node:os";
import pMap from "p-map";
import { expect, vi, type Assertion } from "vitest";
import { z } from "zod";
import { FileSyncEncoding, type FileSyncChangedEventInput, type FileSyncDeletedEventInput } from "../../src/__generated__/graphql.js";
import {
FILE_SYNC_FILES_QUERY,
FILE_SYNC_HASHES_QUERY,
PUBLISH_FILE_SYNC_EVENTS_MUTATION,
REMOTE_FILES_VERSION_QUERY,
REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION,
} from "../../src/services/app/edit-graphql.js";
import { Directory } from "../../src/services/filesync/directory.js";
import { Directory, type Hashes } from "../../src/services/filesync/directory.js";
import { FileSync, isEmptyOrNonExistentDir, type File } from "../../src/services/filesync/filesync.js";
import { isEqualHashes } from "../../src/services/filesync/hashes.js";
import { isNil } from "../../src/services/util/is.js";
import { defaults, omit } from "../../src/services/util/object.js";
import { PromiseSignal } from "../../src/services/util/promise.js";
import type { PartialExcept } from "../types.js";
Expand Down Expand Up @@ -123,6 +127,11 @@ export type SyncScenario = {
* @returns A mock subscription for {@linkcode REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION}.
*/
expectGadgetChangesSubscription: () => MockSubscription<REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION>;

/**
* Asserts that the local and gadget directories have the same hashes.
*/
expectLocalAndGadgetHashesMatch: () => Promise<void>;
};

/**
Expand Down Expand Up @@ -150,6 +159,10 @@ export const makeSyncScenario = async ({
const filesVersionDirs = new Map<bigint, Directory>();
filesVersionDirs.set(1n, filesVersion1Dir);

if (!isEqualHashes(await localDir.hashes(), await gadgetDir.hashes())) {
gadgetFilesVersion = 2n;
}

if (gadgetFilesVersion === 2n) {
await fs.copy(gadgetDir.path, testDirPath("fv-2"));
filesVersionDirs.set(2n, await Directory.init(testDirPath("fv-2")));
Expand Down Expand Up @@ -201,11 +214,70 @@ export const makeSyncScenario = async ({

void nockEditGraphQLResponse({
persist: true,
query: REMOTE_FILES_VERSION_QUERY,
result: () => {
query: FILE_SYNC_HASHES_QUERY,
expectVariables: z.object({ filesVersion: z.string().optional() }).optional(),
result: async (variables) => {
let filesVersion: bigint;
let hashes: Hashes;

if (isNil(variables?.filesVersion)) {
log.debug("sending gadget hashes", { gadgetFilesVersion, variables });
filesVersion = gadgetFilesVersion;
hashes = await gadgetDir.hashes();
} else {
filesVersion = BigInt(variables.filesVersion);
log.debug("sending files version hashes", { filesVersion, variables });
const filesVersionDir = filesVersionDirs.get(filesVersion);
assert(filesVersionDir, `filesVersionDir ${filesync.filesVersion} doesn't exist`);
hashes = await filesVersionDir.hashes();
}

return {
data: {
fileSyncHashes: {
filesVersion: String(filesVersion),
hashes,
},
},
};
},
});

void nockEditGraphQLResponse({
optional: true,
persist: true,
query: FILE_SYNC_FILES_QUERY,
expectVariables: z.object({
filesVersion: z.string().optional(),
paths: z.array(z.string()),
encoding: z.nativeEnum(FileSyncEncoding).optional(),
}),
result: async ({ filesVersion, paths, encoding }) => {
filesVersion ??= String(gadgetFilesVersion);
encoding ??= FileSyncEncoding.Base64;

const filesVersionDir = filesVersionDirs.get(BigInt(filesVersion));
assert(filesVersionDir, `filesVersionDir ${filesync.filesVersion} doesn't exist`);

return {
data: {
remoteFilesVersion: String(gadgetFilesVersion),
fileSyncFiles: {
filesVersion: filesVersion,
files: await pMap(paths, async (filepath) => {
const stats = await fs.stat(filesVersionDir.absolute(filepath));
let content = "";
if (stats.isFile()) {
content = (await fs.readFile(filesVersionDir.absolute(filepath), { encoding })) as string;
}

return {
path: filepath,
mode: stats.mode,
content,
encoding: FileSyncEncoding.Base64,
};
}),
},
},
};
},
Expand Down Expand Up @@ -321,6 +393,12 @@ export const makeSyncScenario = async ({
},

expectGadgetChangesSubscription: () => mockEditGraphQL.expectSubscription(REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION),

expectLocalAndGadgetHashesMatch: async () => {
const localHashes = await localDir.hashes();
const gadgetHashes = await gadgetDir.hashes();
expect(localHashes).toEqual(gadgetHashes);
},
};
};

Expand Down
1 change: 1 addition & 0 deletions spec/commands/sync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ describe("sync", () => {
await expectGadgetDir().resolves.toMatchInlineSnapshot(`
{
".gadget/": "",
".ignore": "tmp",
}
`);
});
Expand Down
Loading

0 comments on commit 5bac25e

Please sign in to comment.