@@ -191,225 +191,10 @@ namespace plugify {
191191 } logging;
192192
193193 // Comprehensive merge implementation
194- void MergeFrom (const Config& other, ConfigSource source = ConfigSource::Override) {
195- // Only merge if the new source has equal or higher priority
196-
197- // Merge Paths
198- if (source >= _sources.paths ) {
199- bool pathsChanged = false ;
200-
201- // Always take baseDir if provided
202- if (!other.paths .baseDir .empty ()) {
203- paths.baseDir = other.paths .baseDir ;
204- pathsChanged = true ;
205- }
206-
207- // Take other paths if they're customized
208- if (other.paths .HasCustomExtensionsDir ()) {
209- paths.extensionsDir = other.paths .extensionsDir ;
210- pathsChanged = true ;
211- }
212- if (other.paths .HasCustomConfigsDir ()) {
213- paths.configsDir = other.paths .configsDir ;
214- pathsChanged = true ;
215- }
216- if (other.paths .HasCustomDataDir ()) {
217- paths.dataDir = other.paths .dataDir ;
218- pathsChanged = true ;
219- }
220- if (other.paths .HasCustomLogsDir ()) {
221- paths.logsDir = other.paths .logsDir ;
222- pathsChanged = true ;
223- }
224- if (other.paths .HasCustomCacheDir ()) {
225- paths.cacheDir = other.paths .cacheDir ;
226- pathsChanged = true ;
227- }
228-
229- if (pathsChanged) {
230- _sources.paths = source;
231- }
232- }
233-
234- // Merge Loading
235- if (source >= _sources.loading ) {
236- bool loadingChanged = false ;
237-
238- if (other.loading .HasCustomPreferOwnSymbols ()) {
239- loading.preferOwnSymbols = other.loading .preferOwnSymbols ;
240- loadingChanged = true ;
241- }
242- if (other.loading .HasCustomMaxConcurrentLoads ()) {
243- loading.maxConcurrentLoads = other.loading .maxConcurrentLoads ;
244- loadingChanged = true ;
245- }
246- if (other.loading .HasCustomLoadTimeout ()) {
247- loading.loadTimeout = other.loading .loadTimeout ;
248- loadingChanged = true ;
249- }
250- if (other.loading .HasCustomExportTimeout ()) {
251- loading.exportTimeout = other.loading .exportTimeout ;
252- loadingChanged = true ;
253- }
254- if (other.loading .HasCustomStartTimeout ()) {
255- loading.startTimeout = other.loading .startTimeout ;
256- loadingChanged = true ;
257- }
258-
259- if (loadingChanged) {
260- _sources.loading = source;
261- }
262- }
263-
264- // Merge Runtime
265- if (source >= _sources.runtime ) {
266- bool runtimeChanged = false ;
267-
268- if (other.runtime .HasCustomUpdateMode ()) {
269- runtime.updateMode = other.runtime .updateMode ;
270- runtimeChanged = true ;
271- }
272- if (other.runtime .HasCustomUpdateInterval ()) {
273- runtime.updateInterval = other.runtime .updateInterval ;
274- runtimeChanged = true ;
275- }
276- if (other.runtime .updateCallback ) {
277- runtime.updateCallback = other.runtime .updateCallback ;
278- runtimeChanged = true ;
279- }
280- if (other.runtime .HasCustomPinToMainThread ()) {
281- runtime.pinToMainThread = other.runtime .pinToMainThread ;
282- runtimeChanged = true ;
283- }
284- if (other.runtime .HasThreadPriority ()) {
285- runtime.threadPriority = other.runtime .threadPriority ;
286- runtimeChanged = true ;
287- }
288-
289- if (runtimeChanged) {
290- _sources.runtime = source;
291- }
292- }
293-
294- // Merge Security
295- if (source >= _sources.security ) {
296- bool securityChanged = false ;
297-
298- // For sets, we have different merge strategies
299- if (source == ConfigSource::Override) {
300- // Override replaces entirely if non-empty
301- if (other.security .HasWhitelist ()) {
302- security.whitelistedExtensions = other.security .whitelistedExtensions ;
303- securityChanged = true ;
304- }
305- if (other.security .HasBlacklist ()) {
306- security.blacklistedExtensions = other.security .blacklistedExtensions ;
307- securityChanged = true ;
308- }
309- if (other.security .HasExcluded ()) {
310- security.excludedDirs = other.security .excludedDirs ;
311- securityChanged = true ;
312- }
313- } else {
314- // Other sources merge/append
315- if (other.security .HasWhitelist ()) {
316- security.whitelistedExtensions .insert (
317- other.security .whitelistedExtensions .begin (),
318- other.security .whitelistedExtensions .end ()
319- );
320- securityChanged = true ;
321- }
322- if (other.security .HasBlacklist ()) {
323- security.blacklistedExtensions .insert (
324- other.security .blacklistedExtensions .begin (),
325- other.security .blacklistedExtensions .end ()
326- );
327- securityChanged = true ;
328- }
329- if (other.security .HasExcluded ()) {
330- security.excludedDirs .insert (
331- other.security .excludedDirs .begin (),
332- other.security .excludedDirs .end ()
333- );
334- securityChanged = true ;
335- }
336- }
337-
338- if (securityChanged) {
339- _sources.security = source;
340- }
341- }
342-
343- // Merge Logging
344- if (source >= _sources.logging ) {
345- bool loggingChanged = false ;
346-
347- if (other.logging .HasCustomSeverity ()) {
348- logging.severity = other.logging .severity ;
349- loggingChanged = true ;
350- }
351- if (other.logging .HasCustomPrintReport ()) {
352- logging.printReport = other.logging .printReport ;
353- loggingChanged = true ;
354- }
355- if (other.logging .HasCustomPrintLoadOrder ()) {
356- logging.printLoadOrder = other.logging .printLoadOrder ;
357- loggingChanged = true ;
358- }
359- if (other.logging .HasCustomPrintDependencyGraph ()) {
360- logging.printDependencyGraph = other.logging .printDependencyGraph ;
361- loggingChanged = true ;
362- }
363- if (other.logging .HasCustomPrintDigraphDot ()) {
364- logging.printDigraphDot = other.logging .printDigraphDot ;
365- loggingChanged = true ;
366- }
367- if (other.logging .HasExportPath ()) {
368- logging.exportDigraphDot = other.logging .exportDigraphDot ;
369- loggingChanged = true ;
370- }
371-
372- if (loggingChanged) {
373- _sources.logging = source;
374- }
375- }
376-
377- // Always resolve paths after merge
378- paths.ResolveRelativePaths ();
379- }
194+ void MergeFrom (const Config& other, ConfigSource source = ConfigSource::Override);
380195
381196 // Alternative merge for selective field updates
382- /* void MergeField(std::string_view fieldPath, const Config& other, ConfigSource source =
383- ConfigSource::Override) {
384- // This allows merging specific fields only
385- if (fieldPath == "paths") {
386- if (source >= _sources.paths) {
387- paths = other.paths;
388- _sources.paths = source;
389- paths.ResolveRelativePaths();
390- }
391- } else if (fieldPath == "loading") {
392- if (source >= _sources.loading) {
393- loading = other.loading;
394- _sources.loading = source;
395- }
396- } else if (fieldPath == "runtime") {
397- if (source >= _sources.runtime) {
398- runtime = other.runtime;
399- _sources.runtime = source;
400- }
401- } else if (fieldPath == "security") {
402- if (source >= _sources.security) {
403- security = other.security;
404- _sources.security = source;
405- }
406- } else if (fieldPath == "logging") {
407- if (source >= _sources.logging) {
408- logging = other.logging;
409- _sources.logging = source;
410- }
411- }
412- }
197+ void MergeField (std::string_view fieldPath, const Config& other, ConfigSource source = ConfigSource::Override);
413198
414199 // Get effective source for debugging
415200 std::string GetSourceInfo () const {
@@ -421,54 +206,15 @@ namespace plugify {
421206 plg::enum_to_string (_sources.security ),
422207 plg::enum_to_string (_sources.logging )
423208 );
424- }*/
209+ }
425210
426211 // Reset to defaults
427212 void Reset () {
428213 *this = Config{};
429214 }
430215
431216 // Validation remains the same
432- Result<void > Validate () const {
433- if (paths.baseDir .empty ()) {
434- return MakeError (" Base directory not set" );
435- }
436-
437- // Check for path collisions
438- using pair = std::pair<std::string_view, const std::filesystem::path*>;
439- std::array pathList = {
440- pair{ " extensions" , &paths.extensionsDir },
441- pair{ " configs" , &paths.configsDir },
442- pair{ " data" , &paths.dataDir },
443- pair{ " logs" , &paths.logsDir },
444- pair{ " cache" , &paths.cacheDir },
445- };
446-
447- for (size_t i = 0 ; i < pathList.size (); ++i) {
448- for (size_t j = i + 1 ; j < pathList.size (); ++j) {
449- if (*pathList[i].second == *pathList[j].second ) {
450- return MakeError (
451- " {} and {} directories are the same: {}" ,
452- pathList[i].first ,
453- pathList[j].first ,
454- plg::as_string (*pathList[i].second )
455- );
456- }
457- }
458- }
459-
460- // Validate runtime config
461- if (runtime.updateMode == UpdateMode::BackgroundThread
462- && runtime.updateInterval <= std::chrono::milliseconds{ 0 }) {
463- return MakeError (" Invalid update interval for background thread mode" );
464- }
465-
466- if (runtime.updateMode == UpdateMode::Callback && !runtime.updateCallback ) {
467- return MakeError (" Update callback not set for callback mode" );
468- }
469-
470- return {};
471- }
217+ Result<void > Validate () const ;
472218
473219 private:
474220 static inline std::unordered_set<std::filesystem::path> DefaultExcludedDirs = {
0 commit comments