Ctrl K
ComunidadGuías…

electron/cloud-sync-plan.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// What one pass of Files does, worked out from three listings of one folder: this computer's (`pc`), My Cloud's
// (`cloud`) and the base (each file as it was when both last matched). Pure: the engine carries the plan out.

// This many files leaving a shared folder at once, and at least this share of it, waits for the person to say so.
export const ASK_DELETES_AT = 10;
export const ASK_DELETES_SHARE = 0.2;

/**
 * A shared folder goes one way, this computer to My Cloud: this computer's version always wins. A file gone from this
 * computer is removed from My Cloud only when the base proves it was there, and never while anything else cannot be read
 * (`unsettled`, or `kept`: links and hard-linked files, present but not carried). Files only My Cloud has (a bot's) stay.
 */
export function planShare({ base, pc, cloud, keptDirs = [] }) {
  const uploads = [], records = [], deletes = [], forgets = [];
  const underKept = (path) => keptDirs.some((dir) => path.startsWith(`${dir}/`));
  for (const [path, file] of pc) {
    if (file.unsettled || file.kept) continue;
    const there = cloud.get(path);
    if (there?.sha256 === file.sha256) {
      const known = base.get(path);
      if (!known || known.sha256 !== file.sha256 || known.size !== file.size || known.mtimeMs !== file.mtimeMs) records.push({ path, sha256: file.sha256, size: file.size, mtimeMs: file.mtimeMs });
      continue;
    }
    uploads.push({ path, sha256: file.sha256, size: file.size, mtimeMs: file.mtimeMs, file: file.file, baseSha256: there?.sha256 ?? null });
  }
  for (const [path, known] of base) {
    if (pc.has(path) || underKept(path)) continue;
    const there = cloud.get(path);
    if (!there) { forgets.push({ path }); continue; }
    deletes.push({ path, baseSha256: there.sha256, size: known.size });
  }
  const ask = deletes.length > 0 && ((pc.size === 0 && base.size > 0) || (deletes.length >= ASK_DELETES_AT && deletes.length >= ASK_DELETES_SHARE * base.size));
  return { uploads, records, deletes, forgets, ask };
}

/**
 * A bot's work comes one way, My Cloud to this computer, and never deletes here. A file the person changed here since it
 * came (size or time differs from the base) is kept as it is: My Cloud's newer version lands beside it (`beside`). A file
 * the person removed here comes back only when My Cloud has a newer version.
 */
export function planOutputs({ base, pc, cloud }) {
  const downloads = [], records = [];
  for (const [path, there] of cloud) {
    const here = pc.get(path), known = base.get(path);
    if (here?.unsettled || here?.kept) continue;
    if (here && here.sha256 === there.sha256) {
      if (!known || known.sha256 !== there.sha256 || known.size !== here.size || known.mtimeMs !== here.mtimeMs) records.push({ path, sha256: there.sha256, size: here.size, mtimeMs: here.mtimeMs });
      continue;
    }
    if (known && known.sha256 === there.sha256) continue;
    if (!here) { downloads.push({ path, sha256: there.sha256, size: there.size, replace: null }); continue; }
    const untouched = Boolean(known && here.size === known.size && here.mtimeMs === known.mtimeMs);
    downloads.push({ path, sha256: there.sha256, size: there.size, replace: untouched ? here : null, beside: !untouched });
  }
  return { downloads, records };
}