Files
odoo-addons/addons/cetmix_tower_git/models/cx_tower_server.py

157 lines
5.5 KiB
Python

# Copyright (C) 2024 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class CxTowerServer(models.Model):
_inherit = "cx.tower.server"
git_project_rel_ids = fields.One2many(
comodel_name="cx.tower.git.project.rel",
inverse_name="server_id",
copy=False,
depends=["git_project_ids"],
groups="cetmix_tower_server.group_manager,cetmix_tower_server.group_root",
)
# Helper field to get all git projects related to server
# IMPORTANT: This field may contain duplicates because of the relation nature!
git_project_ids = fields.Many2many(
comodel_name="cx.tower.git.project",
relation="cx_tower_git_project_rel",
column1="server_id",
column2="git_project_id",
readonly=True,
copy=False,
depends=["git_project_rel_ids"],
groups="cetmix_tower_server.group_manager,cetmix_tower_server.group_root",
)
# ------------------------------
# YAML mixin methods
# ------------------------------
def _get_fields_for_yaml(self):
res = super()._get_fields_for_yaml()
res += [
"git_project_rel_ids",
]
return res
def _get_force_x2m_resolve_models(self):
res = super()._get_force_x2m_resolve_models()
# Add File in order to always try to use existing one
res += ["cx.tower.file"]
return res
def _update_or_create_related_record(
self, model, reference, values, create_immediately=False
):
# Files must be created immediately because they are related
# to both server and git project.
# So if a file is not created immediately when it is created
# for the server, the same file will be created for the git project.
# This will lead to creation of two files with the same content
# for the same server.
if model._name == "cx.tower.file":
create_immediately = True
return super()._update_or_create_related_record(
model, reference, values, create_immediately=create_immediately
)
@api.model
def get_servers_by_git_ref(self, repository_url, head=None, head_type=None):
"""
Return servers linked to a given Git repository reference.
Parameters
----------
repository_url : str
Pre-normalized canonical Git URL
(e.g. ``https://host/owner/repo.git``).
head : str, optional
Branch name, commit SHA, or PR identifier.
head_type : {'branch', 'commit', 'pr'}, optional
Type of the ``head`` argument.
If only ``head`` is provided, it will match across all head types.
If only ``head_type`` is provided, it will filter by type regardless of head
Returns
-------
recordset of cx.tower.server
Matching servers. Empty recordset if no matches.
"""
server_obj = self.env["cx.tower.server"]
# URL MUST be already canonical.
if not repository_url:
return server_obj
# Get repository id by URL
repo_id = self.env["cx.tower.git.repo"]._get_repo_id_by_url(
repository_url, raise_if_invalid=False
)
if not repo_id:
return server_obj
repo = self.env["cx.tower.git.repo"].browse(repo_id)
# Compose domain for remotes
remote_domain = [
("source_id.enabled", "=", True),
("enabled", "=", True),
]
if head:
head = self.env["cx.tower.git.remote"]._sanitize_head(head)
remote_domain.append(("head", "=", head))
if head_type:
remote_domain.append(("head_type", "=", head_type))
# Get remotes
remotes = repo.remote_ids.filtered_domain(remote_domain)
if not remotes:
return server_obj
# Get servers from remotes
servers = remotes.mapped("git_project_id.git_project_rel_ids.server_id")
return servers
def _command_runner_file_using_template_create_file(
self,
file_template_id,
server_dir,
plan_line,
if_file_exists,
**kwargs,
):
"""Override to create git project relation
when creating a file using a template.
"""
file = super()._command_runner_file_using_template_create_file(
file_template_id, server_dir, plan_line, if_file_exists, **kwargs
)
if file and plan_line:
git_project = plan_line.git_project_id
if not git_project:
return file
if plan_line.is_make_copy:
# Remove default_server_ids from context, because this relation
# will be created through git_project_rel_ids.
# default_server_ids will interfere at the moment when
# pairs of values are created through SQL query
# in the method write_real and it does not take into account
# that in this case we are creating a copy of the git project
git_project = git_project.with_context(default_server_ids=False).copy()
self.env["cx.tower.git.project.rel"].create(
{
"git_project_id": git_project.id,
"server_id": self.id,
"file_id": file.id,
"project_format": git_project._default_project_format(),
}
)
return file