Deleting the source project of a pooled fork project breaks the forked project
Summary
Reproduced on 14.4.1-ee
and GitLab.com:
When a user creates a source project and then forks it, there is a situation where the forked project can become broken if the fork relationship is deleted and the source project is deleted.
Users that experience a broken fork will see the following when they attempt to clone a project:
❯ git clone git@gitlab.example.com:group/248276-pool-fork-test-9.git
Cloning into '248276-pool-fork-test-9'...
error: object directory /var/opt/gitlab/git-data/repositories/@pools/e6/29/e629fa6598d732768f7c726b4b621285f9c3b85303900aa912017db7617d8bdb.git/objects does not exist; check .git/objects/info/alternates
error: refs/heads/master does not point to a valid object!
fatal: git upload-pack: not our ref bcdfbfd57c8f3cd6cd65998464bb71a562d49948
fatal: remote error: upload-pack: not our ref bcdfbfd57c8f3cd6cd65998464bb71a562d49948
Steps to reproduce
- Create a public project based on the Ruby on Rails template (this is the source project)
- Create a public fork of the project created in step 1 (this is the forked project). This action should also create a pooled repository under
/var/opt/gitlab/git-data/repositories/@pools
. - Remove the fork relationship from the forked project.
- Delete the source project. This action will also delete the associated pool repository from
/var/opt/gitlab/git-data/repositories/@pools
. - Attempt to clone the project, and see the error in the Summary above.
Example Project
See this example project - this is the forked project after following the reproduction steps above:
https://gitlab.com/anton-bugs/248276/fork/248276
What is the current bug behavior?
If a forked relationship is removed from a forked project and then the source project is deleted, the pool repository is also deleted. This causes the forked project to break because it is still referencing pool repository objects that don't exist.
What is the expected correct behavior?
If a forked relationship is removed from a forked project and then the source project is deleted, GitLab should provide some mechanism to preserve the pool repository objects into the former forked project.
Relevant logs and/or screenshots
Output of checks
This bug happens on GitLab.com
Results of GitLab environment info
Expand for output related to GitLab environment info
(For installations with omnibus-gitlab package run and paste the output of: `sudo gitlab-rake gitlab:env:info`) (For installations from source run and paste the output of: `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
Results of GitLab application Check
Expand for output related to the GitLab application check
(For installations with omnibus-gitlab package run and paste the output of:
sudo gitlab-rake gitlab:check SANITIZE=true
)(For installations from source run and paste the output of:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true
)(we will only investigate if the tests are passing)
Possible fixes
Right. I think I see the bug. There is no gitaly call that can unlink a repository from a repository pool. So when the unlink fork service removes the fork from the repository pool https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/projects/unlink_fork_service.rb#L36 it just removes the database field, but the repo is still physically linked via alternatives. Then when the original project gets deleted, there's no record of any other projects in the pool, so it removes the pool and ruins the physical link