Skip to content

rpc: fix MatchMirror substring ambiguity for exact-match names#227

Open
amitmishra11 wants to merge 2 commits into
videolabs:masterfrom
amitmishra11:fix-mirror-substring-id-match
Open

rpc: fix MatchMirror substring ambiguity for exact-match names#227
amitmishra11 wants to merge 2 commits into
videolabs:masterfrom
amitmishra11:fix-mirror-substring-id-match

Conversation

@amitmishra11

Copy link
Copy Markdown

Problem

mb edit <name> (and other commands that resolve a mirror by name)
matches mirrors using a plain strings.Contains scan over all mirror
names. When a mirror's name happens to be a substring of one or more
other mirror names, it can never be addressed on its own: every mirror
whose name contains the pattern is reported as a match, so the CLI
always prints "Multiple match" and exits.

For example, given mirrors fcix.net, mirror.fcix.net, and
paducahix.mm.fcix.net, running mb edit fcix.net reports all three
as matches instead of resolving to the exact fcix.net mirror.

Fixes #134

Fix

MatchMirror's matching logic is extracted into a standalone,
testable function matchMirrorsByPattern. It now prefers a single
case-insensitive exact match over partial substring matches. If no
exact match exists, it falls back to the previous substring-match
behavior (including returning multiple matches when the pattern is
genuinely ambiguous).

Testing

  • Added rpc/rpc_test.go covering: the exact-match-among-substrings
    regression case from Cannot edit a mirror when its ID is a substring of another #134, case-insensitivity of the exact match,
    preserved multi-match behavior when no exact match exists, no-match,
    and a basic single-substring-match case.
  • Verified the new test fails against the original strings.Contains-only
    logic and passes with the fix.
  • go build / go vet clean for GOOS=linux (this repo's CI target);
    the local Windows dev environment can't compile the process package
    or the original rpc/rpc.go (syscall.SIGUSR2 is Unix-only), which is
    a pre-existing platform limitation unrelated to this change.

This PR was written primarily by Claude Code; I reviewed the change and
ran the tests before submitting.

When a mirror name is a substring of other mirror names (e.g.
"fcix.net" vs. "mirror.fcix.net" and "paducahix.mm.fcix.net"),
MatchMirror used a plain strings.Contains scan, so every mirror
whose name contained the pattern would show up as a match. This
made it impossible to address the shorter mirror on its own via
"mb edit" or similar commands, since the CLI always reported
"Multiple match" and aborted.

Extract the matching logic into matchMirrorsByPattern and prefer
a single case-insensitive exact match over partial substring
matches, while keeping the existing substring-match behavior when
no exact match exists.

Fixes videolabs#134

This PR was written primarily by Claude Code; I reviewed the change
and ran the tests before submitting.
@jbkempf

jbkempf commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Is this AI generated ?

@amitmishra11

Copy link
Copy Markdown
Author

Is this AI generated ?

Yes the changes are AI assisted and I have reviewed the changes.

Comment thread rpc/rpc_test.go Outdated
@@ -0,0 +1,98 @@
// Copyright (c) 2014-2019 Ludovic Fauvet

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You should set this line as Copyright (c) 2026 <your-name-here>, given that you created this file

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed — copyright line updated to reflect the actual author of the new test file.

🤖 Addressed by Claude Code

Comment thread rpc/rpc_test.go Outdated
}

func TestMatchMirrorsByPatternExactMatchAmongSubstrings(t *testing.T) {
// Regression test for https://github.com/etix/mirrorbits/issues/134

@elboulangero elboulangero Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The right URL is https://github.com/videolabs/mirrorbits/issues/134

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed — issue URL corrected to videolabs/mirrorbits/issues/134.

🤖 Addressed by Claude Code

@elboulangero

Copy link
Copy Markdown
Contributor

Can you ask Claude to refactor the tests in order to use sub-tests?

All the tests can be defined by 3 variables:

  • list of mirrors
  • argument for the match function
  • the result we expect (the want variable)

Then the logic to run and check the results is the same for all the tests.

So it should be trivial to use sub-tests and make it all much more concise, only one main test function TestMatchMirrorsByPattern will be needed, I think.

Comment thread rpc/rpc.go Outdated
// (case-insensitive), only that mirror is returned, even if other mirror
// names also contain pattern as a substring. This allows a mirror whose
// name is a substring of other mirror names (e.g. "fcix.net" vs.
// "mirror.fcix.net") to still be matched unambiguously.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I find the description hard to read, so I tried to reword, failed, asked AI for help, ended up with that:

// matchMirrorsByPattern returns a list of mirrors:
// - if the pattern matches a mirror's name exactly, only that mirror is returned
// - otherwise, all mirrors containing the pattern as a substring are returned
// - all matches are case-insensitive
// This allows a mirror whose name is a substring of other mirror names
// (e.g. "fcix.net" vs. "mirror.fcix.net") to still be matched unambiguously.

Please update if you think it's better, or ignore otherwise (this is not super important)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated — adopted the improved wording you suggested.

🤖 Addressed by Claude Code

- Convert 5 separate test functions for matchMirrorsByPattern into a
  single table-driven test using t.Run, as requested by reviewer.
- Fix copyright header on rpc_test.go to reflect the actual author.
- Correct regression test URL from etix/mirrorbits to videolabs/mirrorbits.
- Adopt improved function comment wording suggested by reviewer.
@amitmishra11

Copy link
Copy Markdown
Author

Pushed a follow-up commit addressing all review feedback:

  • Refactored the 5 individual test functions into a single table-driven test using t.Run, parametrised by mirrors, pattern, and expected result.
  • Fixed copyright header to reflect actual authorship.
  • Corrected the regression-test issue URL to videolabs/mirrorbits/issues/134.
  • Adopted the improved matchMirrorsByPattern comment wording.

🤖 Addressed by Claude Code

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.

Cannot edit a mirror when its ID is a substring of another

3 participants