|
1 | 1 | import type { PHP, UniversalPHP } from '@php-wasm/universal'; |
2 | 2 | import { __private__dont__use } from '@php-wasm/universal'; |
3 | | -import { Semaphore, basename, joinPaths } from '@php-wasm/util'; |
| 3 | +import { Semaphore, basename, isParentOf, joinPaths } from '@php-wasm/util'; |
4 | 4 | import { logger } from '@php-wasm/logger'; |
5 | 5 |
|
6 | 6 | export type EmscriptenFS = any; |
@@ -108,28 +108,51 @@ export type FilesystemOperation = |
108 | 108 | | DeleteOperation |
109 | 109 | | RenameOperation; |
110 | 110 |
|
| 111 | +export type FSJournalOptions = { |
| 112 | + excludePaths?: string[]; |
| 113 | + excludeNames?: string[]; |
| 114 | +}; |
| 115 | + |
111 | 116 | export function journalFSEvents( |
112 | 117 | php: PHP, |
113 | 118 | fsRoot: string, |
114 | | - onEntry: (entry: FilesystemOperation) => void = () => {} |
| 119 | + onEntry: (entry: FilesystemOperation) => void = () => {}, |
| 120 | + { excludePaths = [], excludeNames = [] }: FSJournalOptions = {} |
115 | 121 | ) { |
| 122 | + const shouldRecord = (path: string) => |
| 123 | + isParentOf(fsRoot, path) && |
| 124 | + !excludePaths.some((excluded) => isParentOf(excluded, path)) && |
| 125 | + (!excludeNames.length || !excludeNames.includes(basename(path))); |
| 126 | + |
116 | 127 | function bindToCurrentRuntime() { |
117 | 128 | fsRoot = normalizePath(fsRoot); |
118 | 129 | const FS = php[__private__dont__use].FS; |
119 | 130 | const FSHooks = createFSHooks(FS, (entry: FilesystemOperation) => { |
120 | | - // Only journal entries inside the specified root directory. |
121 | | - if (entry.path.startsWith(fsRoot)) { |
| 131 | + const recordSource = shouldRecord(entry.path); |
| 132 | + if (entry.operation !== 'RENAME') { |
| 133 | + if (recordSource) { |
| 134 | + onEntry(entry); |
| 135 | + } |
| 136 | + return; |
| 137 | + } |
| 138 | + const recordDestination = shouldRecord(entry.toPath); |
| 139 | + if (recordSource && recordDestination) { |
122 | 140 | onEntry(entry); |
123 | | - } else if ( |
124 | | - entry.operation === 'RENAME' && |
125 | | - entry.toPath.startsWith(fsRoot) |
126 | | - ) { |
| 141 | + } else if (recordSource) { |
| 142 | + onEntry({ |
| 143 | + operation: 'DELETE', |
| 144 | + path: entry.path, |
| 145 | + nodeType: entry.nodeType, |
| 146 | + }); |
| 147 | + } else if (recordDestination) { |
127 | 148 | for (const op of recordExistingPath( |
128 | 149 | php, |
129 | 150 | entry.path, |
130 | 151 | entry.toPath |
131 | 152 | )) { |
132 | | - onEntry(op); |
| 153 | + if (shouldRecord(op.path)) { |
| 154 | + onEntry(op); |
| 155 | + } |
133 | 156 | } |
134 | 157 | } |
135 | 158 | }); |
|
0 commit comments