You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.0 KiB
165 lines
5.0 KiB
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
import os
|
|
import sys
|
|
from multiprocessing import cpu_count
|
|
from subprocess import check_call
|
|
|
|
import yaml
|
|
from doodbalib import (
|
|
ADDONS_YAML,
|
|
AUTO_REPOS_YAML,
|
|
CORE,
|
|
ODOO_DIR,
|
|
PRIVATE,
|
|
REPOS_YAML,
|
|
SRC_DIR,
|
|
logger,
|
|
)
|
|
|
|
# if the umask matches the `chmod -R u+rwX,g+rX-w,o= /opt/odoo` command the build is faster as we don't need to fix as
|
|
# many permissions after auto aggregation
|
|
UMASK = os.environ.get("UMASK") or "0027"
|
|
UID = int(os.environ.get("UID") or -1)
|
|
GID = int(os.environ.get("GID") or -1)
|
|
DEFAULT_REPO_PATTERN = os.environ.get("DEFAULT_REPO_PATTERN")
|
|
DEFAULT_REPO_PATTERN_ODOO = os.environ.get("DEFAULT_REPO_PATTERN_ODOO")
|
|
log_level = os.environ.get("LOG_LEVEL", "INFO")
|
|
|
|
|
|
def aggregate(config):
|
|
"""Execute git aggregator to pull git code.
|
|
|
|
:param str config:
|
|
Path where to find the ``repos.yaml`` file.
|
|
"""
|
|
logger.info("Running gitaggregate with %s", config)
|
|
|
|
def pre_exec_umask():
|
|
# Download git code with the specified umask, if set, otherwise use "0027"
|
|
os.umask(int(UMASK, 8))
|
|
|
|
pre_execs = [pre_exec_umask]
|
|
|
|
def pre_exec():
|
|
for _exec in pre_execs:
|
|
try:
|
|
_exec()
|
|
except Exception as e:
|
|
logger.error("Error in %s: %s" % (_exec, e))
|
|
logger.exception(e)
|
|
raise
|
|
|
|
if ~GID:
|
|
|
|
def pre_exec_gid():
|
|
# execute git with GID
|
|
os.setgid(GID)
|
|
|
|
pre_execs.append(pre_exec_gid)
|
|
|
|
if ~UID:
|
|
|
|
def pre_exec_uid():
|
|
# execute git with UID
|
|
os.setuid(UID)
|
|
# set odoo home directory
|
|
# (git checks if user has a config in $HOME, and we cannot read /root as odoo user)
|
|
os.environ["HOME"] = "/home/odoo"
|
|
|
|
pre_execs.append(pre_exec_uid)
|
|
|
|
check_call(
|
|
[
|
|
"gitaggregate",
|
|
"--expand-env",
|
|
"--config",
|
|
config,
|
|
"--log-level",
|
|
log_level,
|
|
"--jobs",
|
|
str(cpu_count() or 1),
|
|
"aggregate",
|
|
],
|
|
cwd=SRC_DIR,
|
|
stderr=sys.stderr,
|
|
stdout=sys.stdout,
|
|
preexec_fn=pre_exec,
|
|
)
|
|
|
|
|
|
def origin_for(
|
|
folder,
|
|
default_repo_pattern=DEFAULT_REPO_PATTERN,
|
|
odoo_repo_pattern=DEFAULT_REPO_PATTERN_ODOO,
|
|
):
|
|
"""Guess the default git origin for that folder.
|
|
|
|
:param str folder:
|
|
Normally an absolute path to an expected git repo, whose name should
|
|
match the git repository where it comes from, using the env-supplied
|
|
pattern.
|
|
"""
|
|
base = os.path.basename(folder)
|
|
pattern = default_repo_pattern
|
|
if base == "odoo":
|
|
pattern = odoo_repo_pattern
|
|
return pattern.format(base)
|
|
|
|
|
|
def missing_repos_config():
|
|
"""Find the undefined repositories and return their default configuration.
|
|
|
|
:return dict:
|
|
git-aggregator-ready configuration dict for undefined repositories.
|
|
"""
|
|
defined, expected = set(), {ODOO_DIR}
|
|
# Find the repositories defined by hand
|
|
try:
|
|
with open(REPOS_YAML) as yaml_file:
|
|
for doc in yaml.safe_load_all(yaml_file):
|
|
for repo in doc:
|
|
defined.add(os.path.abspath(os.path.join(SRC_DIR, repo)))
|
|
except (IOError, AttributeError):
|
|
logger.debug("No repositories defined by hand")
|
|
addons_env = {}
|
|
# Find the repositories that should be present
|
|
try:
|
|
with open(ADDONS_YAML) as yaml_file:
|
|
for doc in yaml.safe_load_all(yaml_file):
|
|
env = dict(os.environ, **doc.get("ENV", {}))
|
|
for repo in doc:
|
|
if repo in {PRIVATE, "ONLY", "ENV"}:
|
|
continue
|
|
if repo == CORE:
|
|
repo_path = ODOO_DIR
|
|
else:
|
|
repo_path = os.path.abspath(os.path.join(SRC_DIR, repo))
|
|
if not os.path.exists(repo_path) or os.path.isdir(
|
|
os.path.join(repo_path, ".git")
|
|
):
|
|
expected.add(repo_path)
|
|
addons_env[repo_path] = env
|
|
except (IOError, AttributeError):
|
|
logger.debug("No addons are expected to be present")
|
|
# Find the undefined repositories and generate a config for them
|
|
missing = expected - defined
|
|
config = {}
|
|
for repo_path in missing:
|
|
env = addons_env.get(repo_path, os.environ)
|
|
depth = env["DEPTH_DEFAULT"]
|
|
origin_version = "origin %s" % env["ODOO_VERSION"]
|
|
config[repo_path] = {
|
|
"defaults": {"depth": depth},
|
|
"merges": [origin_version],
|
|
"remotes": {
|
|
"origin": origin_for(
|
|
repo_path,
|
|
env["DEFAULT_REPO_PATTERN"],
|
|
env["DEFAULT_REPO_PATTERN_ODOO"],
|
|
)
|
|
},
|
|
"target": origin_version,
|
|
}
|
|
logger.debug("Generated missing repos config %r", config)
|
|
return config
|