Skip to content

Refactor duplicated code into shared utilities module - #23

Closed
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1782395351-refactor-shared-utilities
Closed

Refactor duplicated code into shared utilities module#23
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1782395351-refactor-shared-utilities

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Extracts 5 duplicated code patterns into scripts/Shared.ps1, sourced by Invoke-BraveDebloat.ps1 before src/ modules and independently by test scripts:

# 1. Object-to-hashtable (was duplicated in Get-ManifestMap + Get-ObjectMap)
ConvertTo-PropertyMap -Object $obj

# 2. Recursive preset resolution with cycle detection (was Resolve-PresetPolicies + Resolve-Preset)
Resolve-PresetEntries -Name $name -Presets $presets [-Seen $seen]

# 3. Unified policy safety validation (merges Assert-PolicySafety + Get-PolicySafetyFinding)
Get-PolicySafetyFindings -PolicyNames $names -Manifest $manifest [-Throw]

# 4. Table formatting wrapper (was inline `| Format-Table -AutoSize -Wrap` x6)
Format-TableOutput -Rows $rows

# 5. Test assertion helpers (moved from Test-Behavior.ps1)
Assert-TextContains / Assert-TextDoesNotContain

Original function names (Get-ManifestMap, Resolve-PresetPolicies, Assert-PolicySafety, Get-PolicySafetyFinding) remain as thin delegation wrappers — public API unchanged.

Net: +137 / −145 lines.

Link to Devin session: https://app.devin.ai/sessions/9f147750e5374db88e58f640d07492cd
Requested by: @osfv

@osfv osfv self-assigned this Jun 25, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces scripts/Shared.ps1 to consolidate five duplicated patterns across Invoke-BraveDebloat.ps1, Test-PolicyManifest.ps1, and Test-Behavior.ps1, replacing identical inline implementations with shared utilities. Original public function names in the production script are retained as thin wrappers, so the external API surface is unchanged.

  • ConvertTo-PropertyMap, Resolve-PresetEntries, Get-PolicySafetyFindings unify object-to-hashtable conversion, recursive preset resolution, and safety validation; all delegating wrappers in src/Manifest.ps1 and src/Common.ps1 preserve identical behavior.
  • Format-TableOutput wraps Format-Table -AutoSize -Wrap and is correctly substituted across all six call sites in src/Reports.ps1.
  • Assert-TextContains / Assert-TextDoesNotContain are moved from Test-Behavior.ps1 into Shared.ps1, making them available to both test scripts (though they also land in the production script's namespace via dot-source, which a previous review comment addressed).

Confidence Score: 5/5

Safe to merge; all delegating wrappers are behaviorally identical to the originals and the safety-critical paths (policy blocking, preset cycle detection, registry WhatIf) are unaffected.

The consolidation is mechanical — every shared implementation is a direct copy of the original, and all public wrappers forward arguments unchanged. The only new issue is a backslash literal inside a Join-Path child argument in Invoke-BraveDebloat.ps1 that would break the dot-source on macOS/Linux; on Windows (the primary target) it works correctly.

Invoke-BraveDebloat.ps1 line 61 — the Join-Path call for Shared.ps1 uses a backslash in the child argument.

Important Files Changed

Filename Overview
Invoke-BraveDebloat.ps1 Adds dot-source of Shared.ps1 before src/ modules (correct load order). Path uses a backslash literal in Join-Path child argument, which breaks the dot-source on macOS/Linux with PowerShell 7.
scripts/Shared.ps1 New shared-utilities module consolidating ConvertTo-PropertyMap, Resolve-PresetEntries, Get-PolicySafetyFindings, Format-TableOutput, and Assert-Text* helpers. Logic is correct; Set-StrictMode applies to callers' scope on dot-source but all current callers already set it, so no impact.
src/Manifest.ps1 Resolve-PresetPolicies and Assert-PolicySafety/Get-PolicySafetyFinding reduced to thin wrappers; delegated implementations are behaviorally identical to the originals.
src/Common.ps1 Get-ManifestMap now delegates to ConvertTo-PropertyMap — thin wrapper preserving public API, no behavioral change.
src/Reports.ps1 All inline Format-Table -AutoSize -Wrap calls replaced with Format-TableOutput; behaviorally equivalent across all six call sites.
scripts/Test-PolicyManifest.ps1 Local Get-ObjectMap and Resolve-Preset replaced by shared counterparts; call sites updated to ConvertTo-PropertyMap and Resolve-PresetEntries. Shared version now also validates non-string preset entries (minor strictness gain).
scripts/Test-Behavior.ps1 Assert-TextContains and Assert-TextDoesNotContain removed from inline definitions and sourced from Shared.ps1; no behavioral change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Invoke-BraveDebloat.ps1] -->|dot-source| S[scripts/Shared.ps1]
    B[scripts/Test-PolicyManifest.ps1] -->|dot-source| S
    C[scripts/Test-Behavior.ps1] -->|dot-source| S

    S --> F1[ConvertTo-PropertyMap]
    S --> F2[Resolve-PresetEntries]
    S --> F3[Get-PolicySafetyFindings]
    S --> F4[Format-TableOutput]
    S --> F5[Assert-TextContains / Assert-TextDoesNotContain]

    A -->|dot-source| M1[src/Common.ps1]
    A -->|dot-source| M2[src/Manifest.ps1]
    A -->|dot-source| M3[src/Reports.ps1]

    M1 -->|thin wrapper| F1
    M2 -->|thin wrappers| F2
    M2 -->|thin wrappers| F3
    M3 -->|calls| F4
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Invoke-BraveDebloat.ps1] -->|dot-source| S[scripts/Shared.ps1]
    B[scripts/Test-PolicyManifest.ps1] -->|dot-source| S
    C[scripts/Test-Behavior.ps1] -->|dot-source| S

    S --> F1[ConvertTo-PropertyMap]
    S --> F2[Resolve-PresetEntries]
    S --> F3[Get-PolicySafetyFindings]
    S --> F4[Format-TableOutput]
    S --> F5[Assert-TextContains / Assert-TextDoesNotContain]

    A -->|dot-source| M1[src/Common.ps1]
    A -->|dot-source| M2[src/Manifest.ps1]
    A -->|dot-source| M3[src/Reports.ps1]

    M1 -->|thin wrapper| F1
    M2 -->|thin wrappers| F2
    M2 -->|thin wrappers| F3
    M3 -->|calls| F4
Loading

Reviews (2): Last reviewed commit: "Refactor duplicated code into shared uti..." | Re-trigger Greptile

Comment thread scripts/Shared.ps1
Comment on lines +99 to +121
function Assert-TextContains {
param(
[Parameter(Mandatory = $true)][string]$Text,
[Parameter(Mandatory = $true)][string]$Expected,
[Parameter(Mandatory = $true)][string]$Context
)

if (-not $Text.Contains($Expected)) {
throw "$Context did not contain expected text: $Expected"
}
}

function Assert-TextDoesNotContain {
param(
[Parameter(Mandatory = $true)][string]$Text,
[Parameter(Mandatory = $true)][string]$Unexpected,
[Parameter(Mandatory = $true)][string]$Context
)

if ($Text.Contains($Unexpected)) {
throw "$Context contained unexpected text: $Unexpected"
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Test-only helpers loaded into production script scope

Assert-TextContains and Assert-TextDoesNotContain are test-only assertions. Because Shared.ps1 is dot-sourced by the production script Invoke-BraveDebloat.ps1, these functions now exist in that script's function namespace. They have no caller in production code and create unnecessary surface area that could confuse future contributors looking at what functions the main script exposes. A cleaner split would keep test-only helpers in a separate scripts/Test-Shared.ps1 (or inline only in Test-Behavior.ps1, their sole consumer) and restrict Shared.ps1 to functions used by both production and test code.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor Fix in Codex

Comment thread scripts/Shared.ps1
Extract repeated patterns into scripts/Shared.ps1:
- ConvertTo-PropertyMap: object-to-hashtable conversion (was Get-ManifestMap / Get-ObjectMap)
- Resolve-PresetEntries: recursive preset resolution with cycle detection
- Get-PolicySafetyFindings: unified policy safety validation with -Throw switch
- Format-TableOutput: table display formatting wrapper
- Assert-TextContains / Assert-TextDoesNotContain: test assertion helpers

src/Common.ps1 Get-ManifestMap now delegates to ConvertTo-PropertyMap.
src/Manifest.ps1 Resolve-PresetPolicies delegates to Resolve-PresetEntries;
Assert-PolicySafety and Get-PolicySafetyFinding delegate to Get-PolicySafetyFindings.
src/Reports.ps1 uses Format-TableOutput instead of inline Format-Table calls.
Test scripts source Shared.ps1 and drop their local duplicates.

Co-Authored-By: adasdasd dasdasdas <fearlemail@gmail.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1782395351-refactor-shared-utilities branch from 2c13709 to 0a26b59 Compare June 25, 2026 13:57
@osfv osfv closed this Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant