cortex-sync 0.4.12 → 0.4.16
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/dist/cli.js +37 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -321,7 +321,8 @@ var GitHubBackend = class {
|
|
|
321
321
|
apiBase;
|
|
322
322
|
headers;
|
|
323
323
|
url(path) {
|
|
324
|
-
|
|
324
|
+
const encoded = path.split("/").map(encodeURIComponent).join("/");
|
|
325
|
+
return `${this.apiBase}/contents/${encoded}`;
|
|
325
326
|
}
|
|
326
327
|
async getSha(path) {
|
|
327
328
|
const res = await fetch(this.url(path), { headers: this.headers });
|
|
@@ -927,6 +928,7 @@ async function pullCommand(opts = {}) {
|
|
|
927
928
|
if (mappingsDirty) await saveMappings(mappings);
|
|
928
929
|
}
|
|
929
930
|
async function* gen() {
|
|
931
|
+
let downloaded = 0;
|
|
930
932
|
for (const path of toPull) {
|
|
931
933
|
const blob = await backend.read("files/" + path);
|
|
932
934
|
const content = decrypt(blob, derived);
|
|
@@ -950,11 +952,16 @@ async function pullCommand(opts = {}) {
|
|
|
950
952
|
if (newEncodedDir !== oldEncodedDir) {
|
|
951
953
|
relativePath = `projects/${newEncodedDir}/${m[3]}`;
|
|
952
954
|
}
|
|
955
|
+
downloaded++;
|
|
956
|
+
process.stdout.write(`\r Downloading\u2026 ${downloaded}/${toPull.length} files`);
|
|
953
957
|
yield { relativePath, content: remappedContent };
|
|
954
958
|
} else {
|
|
959
|
+
downloaded++;
|
|
960
|
+
process.stdout.write(`\r Downloading\u2026 ${downloaded}/${toPull.length} files`);
|
|
955
961
|
yield { relativePath: path, content };
|
|
956
962
|
}
|
|
957
963
|
}
|
|
964
|
+
if (toPull.length > 0) process.stdout.write("\n");
|
|
958
965
|
}
|
|
959
966
|
await adapter.putFiles(gen());
|
|
960
967
|
await saveManifest(MANIFEST_PATH, remote);
|
|
@@ -1064,6 +1071,11 @@ function identifyProject(dir) {
|
|
|
1064
1071
|
}
|
|
1065
1072
|
|
|
1066
1073
|
// src/commands/sync.ts
|
|
1074
|
+
function isSafeGitHubPath(path) {
|
|
1075
|
+
return path.split("/").every(
|
|
1076
|
+
(c) => c.length > 0 && c !== "." && c !== ".." && c !== ".git" && !/[\x00-\x1f\x7f]/.test(c)
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1067
1079
|
async function syncCommand(opts = {}) {
|
|
1068
1080
|
const config = await loadConfig();
|
|
1069
1081
|
const passphrase = await readPassphrase();
|
|
@@ -1072,7 +1084,7 @@ async function syncCommand(opts = {}) {
|
|
|
1072
1084
|
const backend = resolveBackend(config, { target: opts.target });
|
|
1073
1085
|
console.log(`Sync target: ${backend.name}${opts.target ? ` (${opts.target})` : ""}
|
|
1074
1086
|
`);
|
|
1075
|
-
|
|
1087
|
+
process.stdout.write("Reading local files\u2026");
|
|
1076
1088
|
const local = emptyManifest("claude-code");
|
|
1077
1089
|
const contents = /* @__PURE__ */ new Map();
|
|
1078
1090
|
for await (const f of adapter.getFiles()) {
|
|
@@ -1082,8 +1094,10 @@ async function syncCommand(opts = {}) {
|
|
|
1082
1094
|
size: f.content.length,
|
|
1083
1095
|
encryptedSize: 0
|
|
1084
1096
|
};
|
|
1097
|
+
process.stdout.write(`\r Reading\u2026 ${contents.size} files`);
|
|
1085
1098
|
}
|
|
1086
|
-
|
|
1099
|
+
process.stdout.write(`\r ${contents.size} files read${" ".repeat(20)}
|
|
1100
|
+
`);
|
|
1087
1101
|
local.projects = {};
|
|
1088
1102
|
const seenDirs = /* @__PURE__ */ new Set();
|
|
1089
1103
|
for (const [path, content] of contents) {
|
|
@@ -1122,11 +1136,29 @@ async function syncCommand(opts = {}) {
|
|
|
1122
1136
|
console.log(
|
|
1123
1137
|
`Diff \u2014 added: ${diff.added.length}, modified: ${diff.modified.length}, removed: ${diff.removed.length}, unchanged: ${diff.unchanged.length}`
|
|
1124
1138
|
);
|
|
1125
|
-
|
|
1139
|
+
const toUpload = [...diff.added, ...diff.modified];
|
|
1140
|
+
let uploaded = 0;
|
|
1141
|
+
let skipped = 0;
|
|
1142
|
+
for (const path of toUpload) {
|
|
1143
|
+
if (!isSafeGitHubPath(path)) {
|
|
1144
|
+
skipped++;
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1126
1147
|
const content = contents.get(path);
|
|
1127
1148
|
const enc = encrypt(content, derived);
|
|
1128
1149
|
local.files[path].encryptedSize = enc.length;
|
|
1129
|
-
|
|
1150
|
+
try {
|
|
1151
|
+
await backend.write("files/" + path, enc);
|
|
1152
|
+
} catch (e) {
|
|
1153
|
+
process.stdout.write("\n");
|
|
1154
|
+
throw new Error(`Upload failed for "${path}": ${e.message}`);
|
|
1155
|
+
}
|
|
1156
|
+
uploaded++;
|
|
1157
|
+
process.stdout.write(`\r Uploading\u2026 ${uploaded}/${toUpload.length - skipped} files`);
|
|
1158
|
+
}
|
|
1159
|
+
if (toUpload.length > 0) process.stdout.write("\n");
|
|
1160
|
+
if (skipped > 0) {
|
|
1161
|
+
console.warn(` \u26A0 Skipped ${skipped} file(s) with paths incompatible with GitHub (control chars, .git, etc.)`);
|
|
1130
1162
|
}
|
|
1131
1163
|
for (const path of diff.removed) {
|
|
1132
1164
|
await backend.remove("files/" + path);
|