update
This commit is contained in:
65
desktop@marha.de/files.js
Normal file
65
desktop@marha.de/files.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// Dateiabgleich für ~/.claude/projects (Claude-Code-Sitzungen und Memory), nur zwischen PCs.
|
||||
// Reine Logik ohne Dateisystem, damit sie sich testen lässt. sync.js liest und schreibt die Dateien.
|
||||
//
|
||||
// Regeln: Eine Datei geht hoch, wenn sie sich geändert hat und seit einer Stunde nicht angefasst wurde.
|
||||
// Vom Server kommt sie, wenn sie dort neuer ist. Bei Konflikten gewinnt die neuere Änderungszeit.
|
||||
// Verschwundene Dateien werden als Tombstone gemeldet, gelöschte vom Server lokal entfernt.
|
||||
|
||||
// Zeitstempel aus der Änderungszeit der Datei, gleiche Form wie updated bei Terminen
|
||||
export function fileStamp(mtimeSeconds) {
|
||||
return new Date(mtimeSeconds * 1000).toISOString();
|
||||
}
|
||||
|
||||
export function stampToSeconds(stamp) {
|
||||
return Math.floor(Date.parse(stamp) / 1000);
|
||||
}
|
||||
|
||||
// Was hochgeladen wird. local: Map id → mtime in Sekunden. pushed: id → updated, null = als gelöscht gemeldet.
|
||||
// upload: Einträge ohne Inhalt, remove: IDs, die es lokal nicht mehr gibt.
|
||||
export function planPush(local, pushed, nowSeconds, idleSeconds) {
|
||||
const upload = [];
|
||||
for (const [id, mtime] of local) {
|
||||
if (nowSeconds - mtime < idleSeconds)
|
||||
continue;
|
||||
const updated = fileStamp(mtime);
|
||||
if (pushed[id] !== updated)
|
||||
upload.push({id, updated});
|
||||
}
|
||||
const remove = Object.keys(pushed).filter(id => pushed[id] !== null && !local.has(id));
|
||||
return {upload, remove};
|
||||
}
|
||||
|
||||
// Was mit Einträgen vom Server passiert: write, delete oder skip.
|
||||
// mine: der lokale Zeitstempel oder null, damit sync.js den Stand nachhalten kann.
|
||||
export function planPull(remote, local) {
|
||||
return remote.map(file => {
|
||||
const mtime = local.get(file.id);
|
||||
const mine = mtime === undefined ? null : fileStamp(mtime);
|
||||
let action = 'write';
|
||||
if (mine !== null && mine >= file.updated)
|
||||
action = 'skip';
|
||||
else if (file.deleted)
|
||||
action = mine === null ? 'skip' : 'delete';
|
||||
return {file, action, mine};
|
||||
});
|
||||
}
|
||||
|
||||
// Uploads in Pakete teilen, damit eine Anfrage nicht beliebig groß wird
|
||||
export function batches(items, sizeOf, maxBytes) {
|
||||
const out = [];
|
||||
let current = [];
|
||||
let size = 0;
|
||||
for (const item of items) {
|
||||
const bytes = sizeOf(item);
|
||||
if (current.length && size + bytes > maxBytes) {
|
||||
out.push(current);
|
||||
current = [];
|
||||
size = 0;
|
||||
}
|
||||
current.push(item);
|
||||
size += bytes;
|
||||
}
|
||||
if (current.length)
|
||||
out.push(current);
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user