Merge pull request !2922 from rhodecode-enterprise-ce feature/RCCE-360__Repo-deletion

feature: implements the feature to delete a repository completely or leave backup
This commit is contained in:
Andrii Verbytskyi 2025-12-23 12:01:57 +00:00
commit d61a7389cb
8 changed files with 137 additions and 36 deletions

View file

@ -790,6 +790,7 @@ class RepoModel(BaseModel):
fs_remove: bool = True,
cur_user: User = None,
call_events: bool = True,
fs_backup: bool = True,
) -> DeleteRepoResult:
"""
Delete a given repository.
@ -797,11 +798,10 @@ class RepoModel(BaseModel):
:param repo:
:param forks_action:
NOTE: used only in API to enforce action;
If the repository is private, then forks will be removed.
If the repository is public, then forks will be detached.
:param fs_remove: remove(archive) repo from filesystem
NOTE: used only in API to enforce action;
If the repository is private, then forks will be removed.
If the repository is public, then forks will be detached.
:param fs_backup: flag that tells if the repo folder on filesystem should be renamed in a special format or removed completely
"""
repo = self._get_repo(repo)
if not repo:
@ -835,7 +835,7 @@ class RepoModel(BaseModel):
try:
self.sa.delete(repo)
if fs_remove:
self._delete_filesystem_repo(repo)
self._delete_filesystem_repo(repo, backup=fs_backup)
else:
log.debug("skipping removal from filesystem")
old_repo_dict.update(
@ -1115,7 +1115,7 @@ class RepoModel(BaseModel):
raise Exception("Was trying to rename to already existing dir %s" % new_path)
shutil.move(old_path, new_path)
def _delete_filesystem_repo(self, repo):
def _delete_filesystem_repo(self, repo, backup=True):
"""
removes repo from filesystem, the removal is actually made by
added rm__ prefix into dir, and rename internal .hg/.git dirs so this
@ -1123,9 +1123,9 @@ class RepoModel(BaseModel):
by reverting the renames on this repository
:param repo: repo object
:param backup: flag that tells if the repo folder on filesystem should be renamed in a special format or removed completely
"""
rm_path = os.path.join(self.repos_path, repo.repo_name)
repo_group = repo.group
log.info("delete_filesystem_repo: removing repository %s", rm_path)
# disable hg/git internal that it doesn't get detected as repo
alias = repo.repo_type
@ -1134,23 +1134,36 @@ class RepoModel(BaseModel):
config.set("extensions", "largefiles", "")
bare = getattr(repo.scm_instance(config=config), "bare", False)
# skip this for bare git repos
if not bare:
# disable VCS repo
vcs_path = os.path.join(rm_path, ".%s" % alias)
if os.path.exists(vcs_path):
shutil.move(vcs_path, os.path.join(rm_path, "rm__.%s" % alias))
if backup:
# skip this for bare git repos
if not bare:
# disable VCS repo
vcs_path = os.path.join(rm_path, ".%s" % alias)
if os.path.exists(vcs_path):
shutil.move(vcs_path, os.path.join(rm_path, "rm__.%s" % alias))
_now = datetime.datetime.now()
_ms = str(_now.microsecond).rjust(6, "0")
_d = "rm__{}__{}".format(_now.strftime("%Y%m%d_%H%M%S_" + _ms), repo.just_name)
if repo_group:
# if repository is in group, prefix the removal path with the group
args = repo_group.full_path_splitted + [_d]
_d = os.path.join(*args)
repo_group = repo.group
if os.path.isdir(rm_path):
shutil.move(rm_path, os.path.join(self.repos_path, _d))
_now = datetime.datetime.now()
_ms = str(_now.microsecond).rjust(6, "0")
_d = "rm__{}__{}".format(_now.strftime("%Y%m%d_%H%M%S_" + _ms), repo.just_name)
if repo_group:
# if repository is in group, prefix the removal path with the group
args = repo_group.full_path_splitted + [_d]
_d = os.path.join(*args)
if os.path.isdir(rm_path):
shutil.move(rm_path, os.path.join(self.repos_path, _d))
else:
# skip this for bare git repos
if not bare:
# disable VCS repo
vcs_path = os.path.join(rm_path, ".%s" % alias)
if os.path.exists(vcs_path):
shutil.rmtree(vcs_path)
if os.path.exists(rm_path):
shutil.rmtree(rm_path)
# finally cleanup diff-cache if it exists
cached_diffs_dir = repo.cached_diffs_dir