Add priority-based matching of repository identifiers when posting changes.

Review Request #11127 — Created Aug. 7, 2020 and submitted

Information

Review Board
release-3.0.x

Reviewers

Part of the process of posting a change for review is taking the
provided repository identifier (a primary key, name, path, or mirror
path) and fetching the associated repository. If there's a single
repository that matches the identifier against one of those fields, we
use it, but if multiple entries are returned, we tell the client to be
more specific.

There are, however, complex cases out there where multiple repositories
may be returned, each matching a different field against that
identifier. This can happen with archived/hidden repositories, or in
setups trying to transition/consolidate repositories to new central
repositories by setting the repository's name to the same value as
another repository's path.

This change improves the lookup by adding priority-based matching. If
the lookup results in multiple possible repositories, we try to choose a
single one by looking for the following:

  1. Is there only one repository that's visible?
  2. Is there a single repository that has a name matching the identifier?
  3. Is there a single repository that has a path matching the identifier?
  4. Is there a single repository that has a mirror path matching the
    identifier?

Each of those criteria is checked, one-by-one, in order. If any
repository passes that criteria, it will be returned. Otherwise, we
eventually return the same error we did before.

While most setups will never have to go through the priority-based
matching steps, those that do won't see any performance penalty. This
change does not introduce any new SQL queries.

The matching is implemented as Repository.objects.get_best_match(),
allowing the same rules to be applied in queries outside of the API.

Unit tests pass.

Confirmed this fix in a complex production environment. Verified it
solved a "multiple repositories returned" error in their use case.

Summary ID
Add priority-based matching of repository identifiers when posting changes.
Part of the process of posting a change for review is taking the provided repository identifier (a primary key, name, path, or mirror path) and fetching the associated repository. If there's a single repository that matches the identifier against one of those fields, we use it, but if multiple entries are returned, we tell the client to be more specific. There are, however, complex cases out there where multiple repositories may be returned, each matching a different field against that identifier. This can happen with archived/hidden repositories, or in setups trying to transition/consolidate repositories to new central repositories by setting the repository's name to the same value as another repository's path. This change improves the lookup by adding priority-based matching. If the lookup results in multiple possible repositories, we try to choose a single one by looking for the following: 1. Is there only one repository that's visible? 2. Is there a single repository that has a name matching the identifier? 3. Is there a single repository that has a path matching the identifier? 4. Is there a single repository that has a mirror path matching the identifier? Each of those criteria is checked, one-by-one, in order. If any repository passes that criteria, it will be returned. Otherwise, we eventually return the same error we did before. While most setups will never have to go through the priority-based matching steps, those that do won't see any performance penalty. This change does not introduce any new SQL queries. The matching is implemented as `Repository.objects.get_best_match()`, allowing the same rules to be applied in queries outside of the API.
41003d4005ab5c9d01f5793491537c009fe8676e
Description From Last Updated

F841 local variable 'found_repository' is assigned to but never used

reviewbotreviewbot

F841 local variable 'repository1' is assigned to but never used

reviewbotreviewbot

typo: influenc -> influence

daviddavid
Checks run (1 failed, 1 succeeded)
flake8 failed.
JSHint passed.

flake8

chipx86
david
  1. 
      
  2. reviewboard/scmtools/managers.py (Diff revision 2)
     
     
    Show all issues

    typo: influenc -> influence

  3. 
      
chipx86
Review request changed
Status:
Completed
Change Summary:
Pushed to release-3.0.x (194d7e4)