feat(db): add query to perform rename of repository
Related to #894 (closed)
🌱
Context Renaming a GitLab project that contains container repositories is not allowed today. This is mainly because we do not have support for renaming the project's associated repositories to match the new project name.
This MR puts us a step closer to realizing renaming a GitLab project that contains container repositories, by introducing the necessary queries for renaming a repository (and all its sub-repositories) into the registry codebase. Subsequent MRs can then expose this functionality that can be utilized by Gitlab rails when performing a project rename. See #894 (closed) and its parent epic &9761 for more details.
🎰
What's in this MR? This MR introduces three queries to:
- Update all repositories that start with a specific
path
to a newpath
. The new path is constructed with the same parent directory structure as the old-path, only replacing the base path (i.e the last part of the path) to the newly specified base path.
e.g: All repositories with
path
: my-group/my-sub-group/old-repo-name will be changed to my-group/my-sub-group/new-repo-name, wherenew-repo-name
is the newly specified base path
- Update the name of a repository to a new name
- Count the number of repositories under a specific repository path
🐳
Why? This is a build up to #894 (closed), that aims to expose an API endpoint to facilitate renaming a container repository (and all its sub-repositories) when a GitLab project rename is triggered.
⏩
How will these queries be used once exposed via an API The two main queries (to process a rename) added in this MR are expected be run under the following conditions:
- The rename queries are expected to be used together in the same transaction. This means for a rename operation to be successful both the repository rename query (i.e
RenameRepository
) and the sub-repository rename query (i.eRenamePathForSubRepositories
) must succeed. The current plan is to wrap both rename operations in a transaction from a rename request handler (in a subsequent MR) like so:
tx, err := h.db.BeginTx(h.Context, nil)
if err != nil {
...
}
defer tx.Rollback()
rStoreTx := datastore.NewRepositoryStore(tx)
err = rStoreTx.RenameRepository(txCtx, repo.NamespaceID, repo.Path, newPath, newName)
if err != nil {
...
}
err = rStoreTx.RenamePathForSubRepositories(txCtx, repo.NamespaceID, repo.Path, newPath)
if err != nil {
...
}
The pattern above of starting the transaction at the handler level is consistent with other db transaction patterns that exist in the code base today.
- The count query is expected to be run independently (i.e outside the transaction mentioned in 2.) to count how many repositories exist under a given path before proceeding with a rename. This is to make sure the rename queries will only be used against repositories with less than 1000 sub repositories (For GitLab.com, this covers 99.98% of all projects) for now.