Skip to content

Resolve and deduplicate the font set once before processing #209

@MariusStorhaug

Description

Inside the process block, Install-GoogleFont builds the install list with:

foreach ($fontName in $Name) {
    $googleFontsToInstall += $script:GoogleFonts | Where-Object { $_.Name -like $fontName }
}

Two small issues compound across larger inputs:

  1. += on an array allocates a new array on every iteration. For pipeline input or many -Name values this is O(n²).
  2. Overlapping wildcard patterns produce duplicates — e.g. Install-GoogleFont -Name 'Roboto*','Roboto' queues every Roboto variant twice, doubling the download work.

Neither issue is visible on tiny inputs, but together they meaningfully slow down -All-adjacent scenarios and waste bandwidth on overlap.

Request

Current experience

Repeated entries in -Name (or repeated pipeline objects) cause the same font file to be downloaded and installed multiple times in a single command. Building the list also scales quadratically.

Desired experience

The set of font files to install is resolved once, deduplicated, and stored in an efficient collection before any I/O happens. Each file is processed at most once per invocation.

Acceptance criteria

  • The function emits exactly one download/install operation per unique font row, regardless of how many times the row matches via -Name or pipeline input
  • Building the install list is linear in the number of inputs
  • Verbose output reports the deduplicated count
  • Behavior of -All is unchanged (no duplicates exist in that path)

Technical decisions

Collection type: Use [System.Collections.Generic.List[object]] to accumulate matches without += reallocation, then project to a unique set.

Dedup key: A Google Font row is uniquely identified by its URL (each weight/style/file has a distinct CDN URL). Using URL as the dedup key is more correct than Name, because the same Name legitimately appears in many rows (one per variant), and Name + Variant is not always unique across formats.

Place in the function: Resolution stays in the process block (so pipeline input continues to be supported), but the deduplicated set is materialized once before the per-row loop.


Implementation plan

  • Replace the += accumulator with [System.Collections.Generic.List[object]]::new() in src/functions/public/Install-GoogleFont.ps1
  • After resolving matches, deduplicate by URL before entering the install loop
  • Update the existing verbose line "Installing [N] fonts" to reflect the deduplicated count
  • Add a Pester test that calls Install-GoogleFont -Name 'Roboto*','Roboto' and asserts each variant is installed only once

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions