This commit was merged in pull request #802.
This commit is contained in:
@@ -62,16 +62,28 @@ function rotateBackups(filePath: string): void {
|
||||
/**
|
||||
* Sync a source directory to a target, with optional preserve paths.
|
||||
* Replaces the rsync/cp logic from install.sh.
|
||||
*
|
||||
* `isOperatorOwned` is the #791 ownership guard: when supplied, any source path
|
||||
* it flags as operator-owned is never copied (the framework must never write an
|
||||
* operator path). Callers derive it from the shared framework manifest so the TS
|
||||
* and bash sync paths obey one source of truth. This copy is non-destructive —
|
||||
* it never deletes a target file — so honoring the guard is sufficient to leave
|
||||
* operator config untouched.
|
||||
*/
|
||||
export function syncDirectory(
|
||||
source: string,
|
||||
target: string,
|
||||
options: { preserve?: string[]; excludeGit?: boolean } = {},
|
||||
options: {
|
||||
preserve?: string[];
|
||||
excludeGit?: boolean;
|
||||
isOperatorOwned?: (relPath: string) => boolean;
|
||||
} = {},
|
||||
): void {
|
||||
// Guard: source and target are the same directory — nothing to sync
|
||||
if (resolve(source) === resolve(target)) return;
|
||||
|
||||
const preserveSet = new Set(options.preserve ?? []);
|
||||
const isOperatorOwned = options.isOperatorOwned ?? (() => false);
|
||||
|
||||
// Collect files from source
|
||||
function copyRecursive(src: string, dest: string, relBase: string): void {
|
||||
@@ -86,7 +98,7 @@ export function syncDirectory(
|
||||
if (options.excludeGit && (dirName === '.git' || relPath.includes('/.git'))) return;
|
||||
|
||||
// Skip preserved paths at top level
|
||||
if (preserveSet.has(relPath) && existsSync(dest)) return;
|
||||
if (relPath !== '' && preserveSet.has(relPath) && existsSync(dest)) return;
|
||||
|
||||
mkdirSync(dest, { recursive: true });
|
||||
for (const entry of readdirSync(src)) {
|
||||
@@ -101,6 +113,10 @@ export function syncDirectory(
|
||||
// Skip preserved files at top level
|
||||
if (preserveSet.has(relPath) && existsSync(dest)) return;
|
||||
|
||||
// #791: never write an operator-owned path (the framework owns only its
|
||||
// own files; unknown paths resolve to operator and are skipped too).
|
||||
if (isOperatorOwned(relPath)) return;
|
||||
|
||||
mkdirSync(dirname(dest), { recursive: true });
|
||||
copyFileSync(src, dest);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user