From 522d04a8233f66b81abcae4dd04df02d342f35be Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Sat, 25 Jul 2026 16:47:21 -0500 Subject: Normalize repo watch-list entries in addRepo Store the canonical "owner/repo" reconstructed from the parsed parts instead of the raw input, so stray slashes (e.g. "owner/repo/") can't create an entry that silently 404s on refresh. Also compare case-insensitively for duplicates, since GitHub owner/repo names are case-insensitive. Bumps marketing version to 1.0.1. Co-Authored-By: Claude Opus 4.8 --- octosentry/SecurityEventStore.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'octosentry') diff --git a/octosentry/SecurityEventStore.swift b/octosentry/SecurityEventStore.swift index 8f3d0f5..bb92af9 100644 --- a/octosentry/SecurityEventStore.swift +++ b/octosentry/SecurityEventStore.swift @@ -121,13 +121,21 @@ final class SecurityEventStore { watchListErrorMessage = "Enter a repo as \"owner/repo\"." return } + // Store the canonical "owner/repo" rather than the raw input, so + // stray slashes (e.g. "owner/repo/") can't produce a malformed + // entry that silently 404s on refresh. + let repoFullName = "\(parts[0])/\(parts[1])" var state = await persistenceStore.load() - guard !state.watchedRepos.contains(trimmed) else { - watchListErrorMessage = "\(trimmed) is already watched." + // GitHub owner/repo names are case-insensitive, so treat entries + // that differ only in case as the same watched repo. + guard !state.watchedRepos.contains(where: { + $0.caseInsensitiveCompare(repoFullName) == .orderedSame + }) else { + watchListErrorMessage = "\(repoFullName) is already watched." return } - state.watchedRepos.append(trimmed) + state.watchedRepos.append(repoFullName) await persistenceStore.save(state) watchedRepos = state.watchedRepos -- cgit v1.2.3