dorky 4.1.3 → 4.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +50 -31
- package/bin/mcp.js +50 -31
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -23,6 +23,23 @@ const SCOPES = ['https://www.googleapis.com/auth/drive'];
|
|
|
23
23
|
// Helpers
|
|
24
24
|
const readJson = (p) => existsSync(p) ? JSON.parse(readFileSync(p)) : {};
|
|
25
25
|
const writeJson = (p, d) => writeFileSync(p, JSON.stringify(d, null, 2));
|
|
26
|
+
const toPosix = (p) => p ? p.replace(/\\/g, '/') : p;
|
|
27
|
+
const normalizeKeys = (obj) => {
|
|
28
|
+
if (!obj) return {};
|
|
29
|
+
const out = {};
|
|
30
|
+
for (const k of Object.keys(obj)) out[toPosix(k)] = obj[k];
|
|
31
|
+
return out;
|
|
32
|
+
};
|
|
33
|
+
const readMetadata = () => {
|
|
34
|
+
const meta = readJson(METADATA_PATH);
|
|
35
|
+
meta["stage-1-files"] = normalizeKeys(meta["stage-1-files"]);
|
|
36
|
+
meta["uploaded-files"] = normalizeKeys(meta["uploaded-files"]);
|
|
37
|
+
return meta;
|
|
38
|
+
};
|
|
39
|
+
const readHistory = () => {
|
|
40
|
+
const history = existsSync(HISTORY_PATH) ? JSON.parse(readFileSync(HISTORY_PATH)) : [];
|
|
41
|
+
return history.map(e => ({ ...e, files: normalizeKeys(e.files) }));
|
|
42
|
+
};
|
|
26
43
|
|
|
27
44
|
const checkDorkyProject = () => {
|
|
28
45
|
if (!existsSync(DORKY_DIR) && !existsSync(".dorkyignore")) {
|
|
@@ -123,7 +140,7 @@ async function init(storage) {
|
|
|
123
140
|
|
|
124
141
|
async function list(type) {
|
|
125
142
|
checkDorkyProject();
|
|
126
|
-
const meta =
|
|
143
|
+
const meta = readMetadata();
|
|
127
144
|
if (type === "remote") {
|
|
128
145
|
if (!await checkCredentials()) return;
|
|
129
146
|
const creds = readJson(CREDENTIALS_PATH);
|
|
@@ -157,7 +174,7 @@ async function list(type) {
|
|
|
157
174
|
const files = await glob("**/*", { dot: true, ignore: [...exclusions.map(e => `**/${e}/**`), ...exclusions, ".dorky/**", ".dorkyignore", ".git/**", "node_modules/**"] });
|
|
158
175
|
|
|
159
176
|
files.forEach(f => {
|
|
160
|
-
const rel = path.relative(process.cwd(), f);
|
|
177
|
+
const rel = toPosix(path.relative(process.cwd(), f));
|
|
161
178
|
if (rel.includes('.env') || rel.includes('.config')) console.log(chalk.yellow(` ⚠ ${rel} (Potential sensitive file)`));
|
|
162
179
|
else console.log(chalk.gray(` ${rel}`));
|
|
163
180
|
});
|
|
@@ -168,14 +185,15 @@ async function list(type) {
|
|
|
168
185
|
|
|
169
186
|
function add(files) {
|
|
170
187
|
checkDorkyProject();
|
|
171
|
-
const meta =
|
|
188
|
+
const meta = readMetadata();
|
|
172
189
|
const added = [];
|
|
173
190
|
files.forEach(f => {
|
|
174
191
|
if (!existsSync(f)) return console.log(chalk.red(`✖ File not found: ${f}`));
|
|
175
192
|
const hash = md5(readFileSync(f));
|
|
176
|
-
|
|
177
|
-
meta["stage-1-files"][
|
|
178
|
-
|
|
193
|
+
const key = toPosix(f);
|
|
194
|
+
if (meta["stage-1-files"][key]?.hash === hash) return console.log(chalk.gray(`• ${key} (unchanged)`));
|
|
195
|
+
meta["stage-1-files"][key] = { "mime-type": mimeTypes.lookup(f) || "application/octet-stream", hash };
|
|
196
|
+
added.push(key);
|
|
179
197
|
});
|
|
180
198
|
writeJson(METADATA_PATH, meta);
|
|
181
199
|
added.forEach(f => console.log(chalk.green(`✔ Staged: ${f}`)));
|
|
@@ -183,10 +201,11 @@ function add(files) {
|
|
|
183
201
|
|
|
184
202
|
function rm(files) {
|
|
185
203
|
checkDorkyProject();
|
|
186
|
-
const meta =
|
|
204
|
+
const meta = readMetadata();
|
|
187
205
|
const removed = files.filter(f => {
|
|
188
|
-
|
|
189
|
-
|
|
206
|
+
const key = toPosix(f);
|
|
207
|
+
if (!meta["stage-1-files"][key]) return false;
|
|
208
|
+
delete meta["stage-1-files"][key];
|
|
190
209
|
return true;
|
|
191
210
|
});
|
|
192
211
|
writeJson(METADATA_PATH, meta);
|
|
@@ -269,7 +288,7 @@ async function runDrive(fn) {
|
|
|
269
288
|
async function push() {
|
|
270
289
|
checkDorkyProject();
|
|
271
290
|
if (!await checkCredentials()) return;
|
|
272
|
-
const meta =
|
|
291
|
+
const meta = readMetadata();
|
|
273
292
|
const filesToUpload = Object.keys(meta["stage-1-files"])
|
|
274
293
|
.filter(f => !meta["uploaded-files"][f] || meta["stage-1-files"][f].hash !== meta["uploaded-files"][f].hash)
|
|
275
294
|
.map(f => ({ name: f, ...meta["stage-1-files"][f] }));
|
|
@@ -281,7 +300,7 @@ async function push() {
|
|
|
281
300
|
|
|
282
301
|
const commitFiles = { ...meta["stage-1-files"] };
|
|
283
302
|
const commitId = md5(JSON.stringify(commitFiles)).slice(0, 8);
|
|
284
|
-
const history =
|
|
303
|
+
const history = readHistory();
|
|
285
304
|
if (history.length > 0 && history[history.length - 1].id === commitId) return console.log(chalk.yellow("ℹ Already on the latest commit. Nothing to push."));
|
|
286
305
|
|
|
287
306
|
const creds = readJson(CREDENTIALS_PATH);
|
|
@@ -289,14 +308,14 @@ async function push() {
|
|
|
289
308
|
await runS3(creds, async (s3, bucket) => {
|
|
290
309
|
if (filesToUpload.length > 0) {
|
|
291
310
|
await Promise.all(filesToUpload.map(async f => {
|
|
292
|
-
const key = path.join(path.basename(process.cwd()), f.name);
|
|
311
|
+
const key = path.posix.join(path.basename(process.cwd()), f.name);
|
|
293
312
|
await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: readFileSync(f.name) }));
|
|
294
313
|
console.log(chalk.green(`✔ Uploaded: ${f.name}`));
|
|
295
314
|
}));
|
|
296
315
|
}
|
|
297
316
|
if (filesToDelete.length > 0) {
|
|
298
317
|
await Promise.all(filesToDelete.map(async f => {
|
|
299
|
-
const key = path.join(path.basename(process.cwd()), f);
|
|
318
|
+
const key = path.posix.join(path.basename(process.cwd()), f);
|
|
300
319
|
await s3.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
|
|
301
320
|
console.log(chalk.yellow(`✔ Deleted remote: ${f}`));
|
|
302
321
|
}));
|
|
@@ -307,9 +326,9 @@ async function push() {
|
|
|
307
326
|
if (filesToUpload.length > 0) {
|
|
308
327
|
for (const f of filesToUpload) {
|
|
309
328
|
const root = path.basename(process.cwd());
|
|
310
|
-
const parentId = await getFolderId(path.dirname(path.join(root, f.name)), drive);
|
|
329
|
+
const parentId = await getFolderId(path.posix.dirname(path.posix.join(root, f.name)), drive);
|
|
311
330
|
await drive.files.create({
|
|
312
|
-
requestBody: { name: path.basename(f.name), parents: [parentId] },
|
|
331
|
+
requestBody: { name: path.posix.basename(f.name), parents: [parentId] },
|
|
313
332
|
media: { mimeType: f["mime-type"], body: createReadStream(f.name) }
|
|
314
333
|
});
|
|
315
334
|
console.log(chalk.green(`✔ Uploaded: ${f.name}`));
|
|
@@ -318,10 +337,10 @@ async function push() {
|
|
|
318
337
|
if (filesToDelete.length > 0) {
|
|
319
338
|
const root = path.basename(process.cwd());
|
|
320
339
|
for (const f of filesToDelete) {
|
|
321
|
-
const parentId = await getFolderId(path.dirname(path.join(root, f)), drive, false);
|
|
340
|
+
const parentId = await getFolderId(path.posix.dirname(path.posix.join(root, f)), drive, false);
|
|
322
341
|
if (parentId) {
|
|
323
342
|
const res = await drive.files.list({
|
|
324
|
-
q: `name='${path.basename(f)}' and '${parentId}' in parents and trashed=false`,
|
|
343
|
+
q: `name='${path.posix.basename(f)}' and '${parentId}' in parents and trashed=false`,
|
|
325
344
|
fields: 'files(id)'
|
|
326
345
|
});
|
|
327
346
|
if (res.data.files[0]) {
|
|
@@ -341,20 +360,20 @@ async function push() {
|
|
|
341
360
|
writeJson(HISTORY_PATH, history);
|
|
342
361
|
|
|
343
362
|
const root = path.basename(process.cwd());
|
|
344
|
-
const historyPrefix = path.join(root, ".dorky-history", commitId);
|
|
363
|
+
const historyPrefix = path.posix.join(root, ".dorky-history", commitId);
|
|
345
364
|
if (creds.storage === "aws") {
|
|
346
365
|
await runS3(creds, async (s3, bucket) => {
|
|
347
366
|
await Promise.all(Object.keys(commitFiles).map(async f => {
|
|
348
|
-
const key = path.join(historyPrefix, f);
|
|
367
|
+
const key = path.posix.join(historyPrefix, f);
|
|
349
368
|
await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: readFileSync(f) }));
|
|
350
369
|
}));
|
|
351
370
|
});
|
|
352
371
|
} else if (creds.storage === "google-drive") {
|
|
353
372
|
await runDrive(async (drive) => {
|
|
354
373
|
for (const f of Object.keys(commitFiles)) {
|
|
355
|
-
const parentId = await getFolderId(path.join(root, ".dorky-history", commitId, path.dirname(f)), drive);
|
|
374
|
+
const parentId = await getFolderId(path.posix.join(root, ".dorky-history", commitId, path.posix.dirname(f)), drive);
|
|
356
375
|
await drive.files.create({
|
|
357
|
-
requestBody: { name: path.basename(f), parents: [parentId] },
|
|
376
|
+
requestBody: { name: path.posix.basename(f), parents: [parentId] },
|
|
358
377
|
media: { mimeType: commitFiles[f]["mime-type"], body: createReadStream(f) }
|
|
359
378
|
});
|
|
360
379
|
}
|
|
@@ -366,14 +385,14 @@ async function push() {
|
|
|
366
385
|
async function pull() {
|
|
367
386
|
checkDorkyProject();
|
|
368
387
|
if (!await checkCredentials()) return;
|
|
369
|
-
const meta =
|
|
388
|
+
const meta = readMetadata();
|
|
370
389
|
const files = meta["uploaded-files"];
|
|
371
390
|
const creds = readJson(CREDENTIALS_PATH);
|
|
372
391
|
|
|
373
392
|
if (creds.storage === "aws") {
|
|
374
393
|
await runS3(creds, async (s3, bucket) => {
|
|
375
394
|
await Promise.all(Object.keys(files).map(async f => {
|
|
376
|
-
const key = path.join(path.basename(process.cwd()), f);
|
|
395
|
+
const key = path.posix.join(path.basename(process.cwd()), f);
|
|
377
396
|
const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
378
397
|
const dir = path.dirname(f);
|
|
379
398
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
@@ -385,7 +404,7 @@ async function pull() {
|
|
|
385
404
|
await runDrive(async (drive) => {
|
|
386
405
|
const fileList = Object.keys(files).map(k => ({ name: k, ...files[k] }));
|
|
387
406
|
await Promise.all(fileList.map(async f => {
|
|
388
|
-
const res = await drive.files.list({ q: `name='${path.basename(f.name)}' and mimeType!='application/vnd.google-apps.folder'`, fields: 'files(id)' });
|
|
407
|
+
const res = await drive.files.list({ q: `name='${path.posix.basename(f.name)}' and mimeType!='application/vnd.google-apps.folder'`, fields: 'files(id)' });
|
|
389
408
|
if (!res.data.files[0]) return console.log(chalk.red(`✖ Missing remote file: ${f.name}`));
|
|
390
409
|
const data = await drive.files.get({ fileId: res.data.files[0].id, alt: 'media' });
|
|
391
410
|
if (!existsSync(path.dirname(f.name))) mkdirSync(path.dirname(f.name), { recursive: true });
|
|
@@ -398,7 +417,7 @@ async function pull() {
|
|
|
398
417
|
|
|
399
418
|
function log() {
|
|
400
419
|
checkDorkyProject();
|
|
401
|
-
const history =
|
|
420
|
+
const history = readHistory();
|
|
402
421
|
if (!history.length) return console.log(chalk.yellow("ℹ No history found. Push some files first."));
|
|
403
422
|
console.log(chalk.blue.bold("\n📜 Push History:\n"));
|
|
404
423
|
[...history].reverse().forEach((entry, i) => {
|
|
@@ -416,7 +435,7 @@ async function checkout(commitId) {
|
|
|
416
435
|
checkDorkyProject();
|
|
417
436
|
if (!await checkCredentials()) return;
|
|
418
437
|
|
|
419
|
-
const history =
|
|
438
|
+
const history = readHistory();
|
|
420
439
|
const entry = history.find(e => e.id === commitId || e.id.startsWith(commitId));
|
|
421
440
|
if (!entry) return console.log(chalk.red(`✖ Commit not found: ${commitId}. Run --log to see available commits.`));
|
|
422
441
|
|
|
@@ -424,12 +443,12 @@ async function checkout(commitId) {
|
|
|
424
443
|
|
|
425
444
|
const creds = readJson(CREDENTIALS_PATH);
|
|
426
445
|
const root = path.basename(process.cwd());
|
|
427
|
-
const historyPrefix = path.join(root, ".dorky-history", entry.id);
|
|
446
|
+
const historyPrefix = path.posix.join(root, ".dorky-history", entry.id);
|
|
428
447
|
|
|
429
448
|
if (creds.storage === "aws") {
|
|
430
449
|
await runS3(creds, async (s3, bucket) => {
|
|
431
450
|
await Promise.all(Object.keys(entry.files).map(async f => {
|
|
432
|
-
const key = path.join(historyPrefix, f);
|
|
451
|
+
const key = path.posix.join(historyPrefix, f);
|
|
433
452
|
const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
434
453
|
if (!existsSync(path.dirname(f))) mkdirSync(path.dirname(f), { recursive: true });
|
|
435
454
|
writeFileSync(f, await Body.transformToString());
|
|
@@ -439,10 +458,10 @@ async function checkout(commitId) {
|
|
|
439
458
|
} else if (creds.storage === "google-drive") {
|
|
440
459
|
await runDrive(async (drive) => {
|
|
441
460
|
for (const f of Object.keys(entry.files)) {
|
|
442
|
-
const parentId = await getFolderId(path.join(root, ".dorky-history", entry.id, path.dirname(f)), drive, false);
|
|
461
|
+
const parentId = await getFolderId(path.posix.join(root, ".dorky-history", entry.id, path.posix.dirname(f)), drive, false);
|
|
443
462
|
if (!parentId) { console.log(chalk.red(`✖ Remote history folder missing for: ${f}`)); continue; }
|
|
444
463
|
const res = await drive.files.list({
|
|
445
|
-
q: `name='${path.basename(f)}' and '${parentId}' in parents and trashed=false`,
|
|
464
|
+
q: `name='${path.posix.basename(f)}' and '${parentId}' in parents and trashed=false`,
|
|
446
465
|
fields: 'files(id)'
|
|
447
466
|
});
|
|
448
467
|
if (!res.data.files[0]) { console.log(chalk.red(`✖ Missing remote history file: ${f}`)); continue; }
|
|
@@ -454,7 +473,7 @@ async function checkout(commitId) {
|
|
|
454
473
|
});
|
|
455
474
|
}
|
|
456
475
|
|
|
457
|
-
const meta =
|
|
476
|
+
const meta = readMetadata();
|
|
458
477
|
meta["stage-1-files"] = { ...entry.files };
|
|
459
478
|
writeJson(METADATA_PATH, meta);
|
|
460
479
|
console.log(chalk.cyan(`\nℹ Staged state restored to commit ${entry.id}. Run --push to publish this state.`));
|
package/bin/mcp.js
CHANGED
|
@@ -24,6 +24,23 @@ const SCOPES = ["https://www.googleapis.com/auth/drive"];
|
|
|
24
24
|
// Helpers
|
|
25
25
|
const readJson = (p) => existsSync(p) ? JSON.parse(readFileSync(p)) : {};
|
|
26
26
|
const writeJson = (p, d) => writeFileSync(p, JSON.stringify(d, null, 2));
|
|
27
|
+
const toPosix = (p) => p ? p.replace(/\\/g, '/') : p;
|
|
28
|
+
const normalizeKeys = (obj) => {
|
|
29
|
+
if (!obj) return {};
|
|
30
|
+
const out = {};
|
|
31
|
+
for (const k of Object.keys(obj)) out[toPosix(k)] = obj[k];
|
|
32
|
+
return out;
|
|
33
|
+
};
|
|
34
|
+
const readMetadata = () => {
|
|
35
|
+
const meta = readJson(METADATA_PATH);
|
|
36
|
+
meta["stage-1-files"] = normalizeKeys(meta["stage-1-files"]);
|
|
37
|
+
meta["uploaded-files"] = normalizeKeys(meta["uploaded-files"]);
|
|
38
|
+
return meta;
|
|
39
|
+
};
|
|
40
|
+
const readHistory = () => {
|
|
41
|
+
const history = existsSync(HISTORY_PATH) ? JSON.parse(readFileSync(HISTORY_PATH)) : [];
|
|
42
|
+
return history.map(e => ({ ...e, files: normalizeKeys(e.files) }));
|
|
43
|
+
};
|
|
27
44
|
|
|
28
45
|
const checkDorkyProject = () => {
|
|
29
46
|
if (!existsSync(DORKY_DIR) && !existsSync(".dorkyignore")) {
|
|
@@ -94,7 +111,7 @@ async function init(storage) {
|
|
|
94
111
|
|
|
95
112
|
async function list(type) {
|
|
96
113
|
checkDorkyProject();
|
|
97
|
-
const meta =
|
|
114
|
+
const meta = readMetadata();
|
|
98
115
|
const lines = [];
|
|
99
116
|
|
|
100
117
|
if (type === "remote") {
|
|
@@ -130,7 +147,7 @@ async function list(type) {
|
|
|
130
147
|
const files = await glob("**/*", { dot: true, ignore: [...exclusions.map(e => `**/${e}/**`), ...exclusions, ".dorky/**", ".dorkyignore", ".git/**", "node_modules/**"] });
|
|
131
148
|
|
|
132
149
|
files.forEach(f => {
|
|
133
|
-
const rel = path.relative(process.cwd(), f);
|
|
150
|
+
const rel = toPosix(path.relative(process.cwd(), f));
|
|
134
151
|
if (rel.includes(".env") || rel.includes(".config")) lines.push(` ${rel} (Potential sensitive file)`);
|
|
135
152
|
else lines.push(` ${rel}`);
|
|
136
153
|
});
|
|
@@ -143,14 +160,15 @@ async function list(type) {
|
|
|
143
160
|
|
|
144
161
|
function add(files) {
|
|
145
162
|
checkDorkyProject();
|
|
146
|
-
const meta =
|
|
163
|
+
const meta = readMetadata();
|
|
147
164
|
const results = [];
|
|
148
165
|
files.forEach(f => {
|
|
149
166
|
if (!existsSync(f)) { results.push(`File not found: ${f}`); return; }
|
|
150
167
|
const hash = md5(readFileSync(f));
|
|
151
|
-
|
|
152
|
-
meta["stage-1-files"][
|
|
153
|
-
|
|
168
|
+
const key = toPosix(f);
|
|
169
|
+
if (meta["stage-1-files"][key]?.hash === hash) { results.push(`${key} (unchanged)`); return; }
|
|
170
|
+
meta["stage-1-files"][key] = { "mime-type": mimeTypes.lookup(f) || "application/octet-stream", hash };
|
|
171
|
+
results.push(`Staged: ${key}`);
|
|
154
172
|
});
|
|
155
173
|
writeJson(METADATA_PATH, meta);
|
|
156
174
|
return results.join("\n");
|
|
@@ -158,10 +176,11 @@ function add(files) {
|
|
|
158
176
|
|
|
159
177
|
function rm(files) {
|
|
160
178
|
checkDorkyProject();
|
|
161
|
-
const meta =
|
|
179
|
+
const meta = readMetadata();
|
|
162
180
|
const removed = files.filter(f => {
|
|
163
|
-
|
|
164
|
-
|
|
181
|
+
const key = toPosix(f);
|
|
182
|
+
if (!meta["stage-1-files"][key]) return false;
|
|
183
|
+
delete meta["stage-1-files"][key];
|
|
165
184
|
return true;
|
|
166
185
|
});
|
|
167
186
|
writeJson(METADATA_PATH, meta);
|
|
@@ -236,7 +255,7 @@ async function runDrive(fn) {
|
|
|
236
255
|
async function push() {
|
|
237
256
|
checkDorkyProject();
|
|
238
257
|
if (!await checkCredentials()) return "Credentials not found. Please run init first.";
|
|
239
|
-
const meta =
|
|
258
|
+
const meta = readMetadata();
|
|
240
259
|
const filesToUpload = Object.keys(meta["stage-1-files"])
|
|
241
260
|
.filter(f => !meta["uploaded-files"][f] || meta["stage-1-files"][f].hash !== meta["uploaded-files"][f].hash)
|
|
242
261
|
.map(f => ({ name: f, ...meta["stage-1-files"][f] }));
|
|
@@ -246,7 +265,7 @@ async function push() {
|
|
|
246
265
|
|
|
247
266
|
const commitFiles = { ...meta["stage-1-files"] };
|
|
248
267
|
const commitId = md5(JSON.stringify(commitFiles)).slice(0, 8);
|
|
249
|
-
const history =
|
|
268
|
+
const history = readHistory();
|
|
250
269
|
if (history.length > 0 && history[history.length - 1].id === commitId) return "Already on the latest commit. Nothing to push.";
|
|
251
270
|
|
|
252
271
|
const creds = readJson(CREDENTIALS_PATH);
|
|
@@ -256,14 +275,14 @@ async function push() {
|
|
|
256
275
|
await runS3(creds, async (s3, bucket) => {
|
|
257
276
|
if (filesToUpload.length > 0) {
|
|
258
277
|
await Promise.all(filesToUpload.map(async f => {
|
|
259
|
-
const key = path.join(path.basename(process.cwd()), f.name);
|
|
278
|
+
const key = path.posix.join(path.basename(process.cwd()), f.name);
|
|
260
279
|
await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: readFileSync(f.name) }));
|
|
261
280
|
results.push(`Uploaded: ${f.name}`);
|
|
262
281
|
}));
|
|
263
282
|
}
|
|
264
283
|
if (filesToDelete.length > 0) {
|
|
265
284
|
await Promise.all(filesToDelete.map(async f => {
|
|
266
|
-
const key = path.join(path.basename(process.cwd()), f);
|
|
285
|
+
const key = path.posix.join(path.basename(process.cwd()), f);
|
|
267
286
|
await s3.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
|
|
268
287
|
results.push(`Deleted remote: ${f}`);
|
|
269
288
|
}));
|
|
@@ -274,9 +293,9 @@ async function push() {
|
|
|
274
293
|
if (filesToUpload.length > 0) {
|
|
275
294
|
for (const f of filesToUpload) {
|
|
276
295
|
const root = path.basename(process.cwd());
|
|
277
|
-
const parentId = await getFolderId(path.dirname(path.join(root, f.name)), drive);
|
|
296
|
+
const parentId = await getFolderId(path.posix.dirname(path.posix.join(root, f.name)), drive);
|
|
278
297
|
await drive.files.create({
|
|
279
|
-
requestBody: { name: path.basename(f.name), parents: [parentId] },
|
|
298
|
+
requestBody: { name: path.posix.basename(f.name), parents: [parentId] },
|
|
280
299
|
media: { mimeType: f["mime-type"], body: createReadStream(f.name) }
|
|
281
300
|
});
|
|
282
301
|
results.push(`Uploaded: ${f.name}`);
|
|
@@ -285,9 +304,9 @@ async function push() {
|
|
|
285
304
|
if (filesToDelete.length > 0) {
|
|
286
305
|
const root = path.basename(process.cwd());
|
|
287
306
|
for (const f of filesToDelete) {
|
|
288
|
-
const parentId = await getFolderId(path.dirname(path.join(root, f)), drive, false);
|
|
307
|
+
const parentId = await getFolderId(path.posix.dirname(path.posix.join(root, f)), drive, false);
|
|
289
308
|
if (parentId) {
|
|
290
|
-
const res = await drive.files.list({ q: `name='${path.basename(f)}' and '${parentId}' in parents and trashed=false`, fields: "files(id)" });
|
|
309
|
+
const res = await drive.files.list({ q: `name='${path.posix.basename(f)}' and '${parentId}' in parents and trashed=false`, fields: "files(id)" });
|
|
291
310
|
if (res.data.files[0]) {
|
|
292
311
|
await drive.files.delete({ fileId: res.data.files[0].id });
|
|
293
312
|
results.push(`Deleted remote: ${f}`);
|
|
@@ -305,20 +324,20 @@ async function push() {
|
|
|
305
324
|
writeJson(HISTORY_PATH, history);
|
|
306
325
|
|
|
307
326
|
const root = path.basename(process.cwd());
|
|
308
|
-
const historyPrefix = path.join(root, ".dorky-history", commitId);
|
|
327
|
+
const historyPrefix = path.posix.join(root, ".dorky-history", commitId);
|
|
309
328
|
if (creds.storage === "aws") {
|
|
310
329
|
await runS3(creds, async (s3, bucket) => {
|
|
311
330
|
await Promise.all(Object.keys(commitFiles).map(async f => {
|
|
312
|
-
const key = path.join(historyPrefix, f);
|
|
331
|
+
const key = path.posix.join(historyPrefix, f);
|
|
313
332
|
await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: readFileSync(f) }));
|
|
314
333
|
}));
|
|
315
334
|
});
|
|
316
335
|
} else if (creds.storage === "google-drive") {
|
|
317
336
|
await runDrive(async (drive) => {
|
|
318
337
|
for (const f of Object.keys(commitFiles)) {
|
|
319
|
-
const parentId = await getFolderId(path.join(root, ".dorky-history", commitId, path.dirname(f)), drive);
|
|
338
|
+
const parentId = await getFolderId(path.posix.join(root, ".dorky-history", commitId, path.posix.dirname(f)), drive);
|
|
320
339
|
await drive.files.create({
|
|
321
|
-
requestBody: { name: path.basename(f), parents: [parentId] },
|
|
340
|
+
requestBody: { name: path.posix.basename(f), parents: [parentId] },
|
|
322
341
|
media: { mimeType: commitFiles[f]["mime-type"], body: createReadStream(f) }
|
|
323
342
|
});
|
|
324
343
|
}
|
|
@@ -332,7 +351,7 @@ async function push() {
|
|
|
332
351
|
async function pull() {
|
|
333
352
|
checkDorkyProject();
|
|
334
353
|
if (!await checkCredentials()) return "Credentials not found. Please run init first.";
|
|
335
|
-
const meta =
|
|
354
|
+
const meta = readMetadata();
|
|
336
355
|
const files = meta["uploaded-files"];
|
|
337
356
|
const creds = readJson(CREDENTIALS_PATH);
|
|
338
357
|
const results = [];
|
|
@@ -340,7 +359,7 @@ async function pull() {
|
|
|
340
359
|
if (creds.storage === "aws") {
|
|
341
360
|
await runS3(creds, async (s3, bucket) => {
|
|
342
361
|
await Promise.all(Object.keys(files).map(async f => {
|
|
343
|
-
const key = path.join(path.basename(process.cwd()), f);
|
|
362
|
+
const key = path.posix.join(path.basename(process.cwd()), f);
|
|
344
363
|
const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
345
364
|
const dir = path.dirname(f);
|
|
346
365
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
@@ -352,7 +371,7 @@ async function pull() {
|
|
|
352
371
|
await runDrive(async (drive) => {
|
|
353
372
|
const fileList = Object.keys(files).map(k => ({ name: k, ...files[k] }));
|
|
354
373
|
await Promise.all(fileList.map(async f => {
|
|
355
|
-
const res = await drive.files.list({ q: `name='${path.basename(f.name)}' and mimeType!='application/vnd.google-apps.folder'`, fields: "files(id)" });
|
|
374
|
+
const res = await drive.files.list({ q: `name='${path.posix.basename(f.name)}' and mimeType!='application/vnd.google-apps.folder'`, fields: "files(id)" });
|
|
356
375
|
if (!res.data.files[0]) { results.push(`Missing remote file: ${f.name}`); return; }
|
|
357
376
|
const data = await drive.files.get({ fileId: res.data.files[0].id, alt: "media" });
|
|
358
377
|
if (!existsSync(path.dirname(f.name))) mkdirSync(path.dirname(f.name), { recursive: true });
|
|
@@ -367,7 +386,7 @@ async function pull() {
|
|
|
367
386
|
|
|
368
387
|
function log() {
|
|
369
388
|
checkDorkyProject();
|
|
370
|
-
const history =
|
|
389
|
+
const history = readHistory();
|
|
371
390
|
if (!history.length) return "No history found. Push some files first.";
|
|
372
391
|
|
|
373
392
|
const lines = ["Push History:"];
|
|
@@ -387,19 +406,19 @@ async function checkout(commitId) {
|
|
|
387
406
|
checkDorkyProject();
|
|
388
407
|
if (!await checkCredentials()) return "Credentials not found. Please run init first.";
|
|
389
408
|
|
|
390
|
-
const history =
|
|
409
|
+
const history = readHistory();
|
|
391
410
|
const entry = history.find(e => e.id === commitId || e.id.startsWith(commitId));
|
|
392
411
|
if (!entry) return `Commit not found: ${commitId}. Run log to see available commits.`;
|
|
393
412
|
|
|
394
413
|
const creds = readJson(CREDENTIALS_PATH);
|
|
395
414
|
const root = path.basename(process.cwd());
|
|
396
|
-
const historyPrefix = path.join(root, ".dorky-history", entry.id);
|
|
415
|
+
const historyPrefix = path.posix.join(root, ".dorky-history", entry.id);
|
|
397
416
|
const results = [`Checking out commit ${entry.id} (${new Date(entry.timestamp).toLocaleString()}):`];
|
|
398
417
|
|
|
399
418
|
if (creds.storage === "aws") {
|
|
400
419
|
await runS3(creds, async (s3, bucket) => {
|
|
401
420
|
await Promise.all(Object.keys(entry.files).map(async f => {
|
|
402
|
-
const key = path.join(historyPrefix, f);
|
|
421
|
+
const key = path.posix.join(historyPrefix, f);
|
|
403
422
|
const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
404
423
|
if (!existsSync(path.dirname(f))) mkdirSync(path.dirname(f), { recursive: true });
|
|
405
424
|
writeFileSync(f, await Body.transformToString());
|
|
@@ -409,9 +428,9 @@ async function checkout(commitId) {
|
|
|
409
428
|
} else if (creds.storage === "google-drive") {
|
|
410
429
|
await runDrive(async (drive) => {
|
|
411
430
|
for (const f of Object.keys(entry.files)) {
|
|
412
|
-
const parentId = await getFolderId(path.join(root, ".dorky-history", entry.id, path.dirname(f)), drive, false);
|
|
431
|
+
const parentId = await getFolderId(path.posix.join(root, ".dorky-history", entry.id, path.posix.dirname(f)), drive, false);
|
|
413
432
|
if (!parentId) { results.push(`Remote history folder missing for: ${f}`); continue; }
|
|
414
|
-
const res = await drive.files.list({ q: `name='${path.basename(f)}' and '${parentId}' in parents and trashed=false`, fields: "files(id)" });
|
|
433
|
+
const res = await drive.files.list({ q: `name='${path.posix.basename(f)}' and '${parentId}' in parents and trashed=false`, fields: "files(id)" });
|
|
415
434
|
if (!res.data.files[0]) { results.push(`Missing remote history file: ${f}`); continue; }
|
|
416
435
|
const data = await drive.files.get({ fileId: res.data.files[0].id, alt: "media" });
|
|
417
436
|
if (!existsSync(path.dirname(f))) mkdirSync(path.dirname(f), { recursive: true });
|
|
@@ -421,7 +440,7 @@ async function checkout(commitId) {
|
|
|
421
440
|
});
|
|
422
441
|
}
|
|
423
442
|
|
|
424
|
-
const meta =
|
|
443
|
+
const meta = readMetadata();
|
|
425
444
|
meta["stage-1-files"] = { ...entry.files };
|
|
426
445
|
writeJson(METADATA_PATH, meta);
|
|
427
446
|
results.push(`Staged state restored to commit ${entry.id}. Run push to publish this state.`);
|