[UPD] script Format
This commit is contained in:
parent
bee6d50018
commit
36ae1d9beb
8 changed files with 171 additions and 227 deletions
|
|
@ -96,9 +96,7 @@ def commit_by_directory():
|
|||
run_git_command(f'cd "{config.path}" && git rm -r {directory}')
|
||||
|
||||
# Crée le commit
|
||||
commit_message = (
|
||||
f"[{mig_prefix_msg}] {directory}: Migration to {config.odoo_version}"
|
||||
)
|
||||
commit_message = f"[{mig_prefix_msg}] {directory}: Migration to {config.odoo_version}"
|
||||
commit_result = run_git_command(
|
||||
f'cd "{config.path}" && git commit -m "{commit_message}"'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,28 +10,31 @@ def get_db_list_xmlrpc(odoo_url):
|
|||
Retrieves the list of Odoo databases using the XML-RPC API.
|
||||
"""
|
||||
try:
|
||||
common = xmlrpc.client.ServerProxy(f'{odoo_url}/xmlrpc/db')
|
||||
common = xmlrpc.client.ServerProxy(f"{odoo_url}/xmlrpc/db")
|
||||
db_list = common.list()
|
||||
return db_list
|
||||
except xmlrpc.client.Fault as e:
|
||||
print(f"XML-RPC Error: {e.faultCode} - {e.faultString}", file=sys.stderr)
|
||||
print(
|
||||
f"XML-RPC Error: {e.faultCode} - {e.faultString}", file=sys.stderr
|
||||
)
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"Connection Error: {e}", file=sys.stderr)
|
||||
return []
|
||||
|
||||
|
||||
# --- CLI using Click ---
|
||||
@click.command()
|
||||
@click.option(
|
||||
'--odoo-url',
|
||||
default='http://localhost:8069',
|
||||
help='URL of the Odoo server.',
|
||||
show_default=True
|
||||
"--odoo-url",
|
||||
default="http://localhost:8069",
|
||||
help="URL of the Odoo server.",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option(
|
||||
'--raw',
|
||||
"--raw",
|
||||
is_flag=True,
|
||||
help='Output one database per line, without extra formatting. Useful for scripting.'
|
||||
help="Output one database per line, without extra formatting. Useful for scripting.",
|
||||
)
|
||||
def list_databases(odoo_url, raw=False):
|
||||
"""
|
||||
|
|
@ -56,5 +59,5 @@ def list_databases(odoo_url, raw=False):
|
|||
|
||||
|
||||
# --- Script Execution ---
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
list_databases()
|
||||
|
|
|
|||
|
|
@ -151,8 +151,7 @@ Use --production-ready for /srv/git (requires root).
|
|||
type=int,
|
||||
default=DEFAULT_JOBS,
|
||||
help=(
|
||||
"Parallel jobs for init/remote/push"
|
||||
f" (default: {DEFAULT_JOBS})"
|
||||
"Parallel jobs for init/remote/push" f" (default: {DEFAULT_JOBS})"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
|
|
@ -247,11 +246,7 @@ def get_erplibre_root_project(erplibre_root):
|
|||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
revision = (
|
||||
result.stdout.strip()
|
||||
if result.returncode == 0
|
||||
else "master"
|
||||
)
|
||||
revision = result.stdout.strip() if result.returncode == 0 else "master"
|
||||
|
||||
return {
|
||||
"name": ERPLIBRE_REPO_NAME,
|
||||
|
|
@ -278,19 +273,13 @@ async def _init_single_bare_repo(git_path, project, semaphore):
|
|||
return "skipped"
|
||||
|
||||
_logger.info(f" Creating: {bare_path}")
|
||||
_, err, rc = await _run_git(
|
||||
"git", "init", "--bare", bare_path
|
||||
)
|
||||
_, err, rc = await _run_git("git", "init", "--bare", bare_path)
|
||||
if rc != 0:
|
||||
_logger.warning(
|
||||
f" Init failed: {bare_path}: {err.strip()}"
|
||||
)
|
||||
_logger.warning(f" Init failed: {bare_path}: {err.strip()}")
|
||||
return "error"
|
||||
|
||||
# Enable git daemon export
|
||||
export_file = os.path.join(
|
||||
bare_path, "git-daemon-export-ok"
|
||||
)
|
||||
export_file = os.path.join(bare_path, "git-daemon-export-ok")
|
||||
open(export_file, "w").close()
|
||||
|
||||
# Allow pushing from shallow clones
|
||||
|
|
@ -312,10 +301,7 @@ async def init_bare_repos(git_path, projects, jobs):
|
|||
semaphore = asyncio.Semaphore(jobs)
|
||||
|
||||
results = await asyncio.gather(
|
||||
*[
|
||||
_init_single_bare_repo(git_path, p, semaphore)
|
||||
for p in projects
|
||||
]
|
||||
*[_init_single_bare_repo(git_path, p, semaphore) for p in projects]
|
||||
)
|
||||
|
||||
created = results.count("created")
|
||||
|
|
@ -352,9 +338,7 @@ async def _add_single_remote(
|
|||
):
|
||||
"""Add or update remote for a single repo (async)."""
|
||||
async with semaphore:
|
||||
repo_path = os.path.join(
|
||||
erplibre_root, project["path"]
|
||||
)
|
||||
repo_path = os.path.join(erplibre_root, project["path"])
|
||||
if not os.path.isdir(repo_path):
|
||||
_logger.warning(f" Not found: {repo_path}")
|
||||
return "error"
|
||||
|
|
@ -368,9 +352,7 @@ async def _add_single_remote(
|
|||
)
|
||||
|
||||
# Check if remote already exists
|
||||
stdout, _, _ = await _run_git(
|
||||
"git", "-C", repo_path, "remote"
|
||||
)
|
||||
stdout, _, _ = await _run_git("git", "-C", repo_path, "remote")
|
||||
existing_remotes = stdout.strip().split("\n")
|
||||
|
||||
if remote_name in existing_remotes:
|
||||
|
|
@ -403,8 +385,7 @@ async def _add_single_remote(
|
|||
)
|
||||
if rc != 0:
|
||||
_logger.warning(
|
||||
f" add failed for"
|
||||
f" {project['path']}: {err.strip()}"
|
||||
f" add failed for" f" {project['path']}: {err.strip()}"
|
||||
)
|
||||
return "error"
|
||||
_logger.info(f" Added: {project['path']}")
|
||||
|
|
@ -447,10 +428,7 @@ async def add_remotes(
|
|||
added = results.count("added")
|
||||
updated = results.count("updated")
|
||||
errors = results.count("error")
|
||||
print(
|
||||
f"Remotes: {added} added, {updated} updated,"
|
||||
f" {errors} errors"
|
||||
)
|
||||
print(f"Remotes: {added} added, {updated} updated," f" {errors} errors")
|
||||
|
||||
|
||||
# --- Async workers for push ---
|
||||
|
|
@ -458,9 +436,7 @@ async def add_remotes(
|
|||
|
||||
async def _is_detached_head(repo_path):
|
||||
"""Check if a repo is in detached HEAD state."""
|
||||
_, _, rc = await _run_git(
|
||||
"git", "-C", repo_path, "symbolic-ref", "HEAD"
|
||||
)
|
||||
_, _, rc = await _run_git("git", "-C", repo_path, "symbolic-ref", "HEAD")
|
||||
return rc != 0
|
||||
|
||||
|
||||
|
|
@ -471,9 +447,7 @@ async def _checkout_manifest_branch(repo_path, revision):
|
|||
on the exact commit. We create/checkout a local branch
|
||||
matching the manifest revision so git push works.
|
||||
"""
|
||||
branch = (
|
||||
revision.split("/")[-1] if "/" in revision else revision
|
||||
)
|
||||
branch = revision.split("/")[-1] if "/" in revision else revision
|
||||
|
||||
# Check if local branch already exists
|
||||
_, _, rc = await _run_git(
|
||||
|
|
@ -485,9 +459,7 @@ async def _checkout_manifest_branch(repo_path, revision):
|
|||
f"refs/heads/{branch}",
|
||||
)
|
||||
if rc == 0:
|
||||
await _run_git(
|
||||
"git", "-C", repo_path, "checkout", branch
|
||||
)
|
||||
await _run_git("git", "-C", repo_path, "checkout", branch)
|
||||
else:
|
||||
await _run_git(
|
||||
"git",
|
||||
|
|
@ -514,9 +486,7 @@ async def _update_bare_head(git_path, project):
|
|||
revision = project.get("revision", "")
|
||||
if not revision:
|
||||
return
|
||||
branch = (
|
||||
revision.split("/")[-1] if "/" in revision else revision
|
||||
)
|
||||
branch = revision.split("/")[-1] if "/" in revision else revision
|
||||
await _run_git(
|
||||
"git",
|
||||
"-C",
|
||||
|
|
@ -529,20 +499,10 @@ async def _update_bare_head(git_path, project):
|
|||
|
||||
async def _try_unshallow(repo_path, project, remote_name):
|
||||
"""Try to unshallow a repo by fetching full history."""
|
||||
shallow_file = os.path.join(
|
||||
repo_path, ".git", "shallow"
|
||||
)
|
||||
_logger.info(
|
||||
f" Unshallowing {project['path']}..."
|
||||
)
|
||||
stdout, _, _ = await _run_git(
|
||||
"git", "-C", repo_path, "remote"
|
||||
)
|
||||
remotes = [
|
||||
r
|
||||
for r in stdout.strip().split("\n")
|
||||
if r and r != remote_name
|
||||
]
|
||||
shallow_file = os.path.join(repo_path, ".git", "shallow")
|
||||
_logger.info(f" Unshallowing {project['path']}...")
|
||||
stdout, _, _ = await _run_git("git", "-C", repo_path, "remote")
|
||||
remotes = [r for r in stdout.strip().split("\n") if r and r != remote_name]
|
||||
manifest_remote = project.get("remote", "")
|
||||
if manifest_remote in remotes:
|
||||
remotes.remove(manifest_remote)
|
||||
|
|
@ -562,9 +522,7 @@ async def _try_unshallow(repo_path, project, remote_name):
|
|||
except asyncio.TimeoutError:
|
||||
continue
|
||||
if not os.path.exists(shallow_file):
|
||||
_logger.info(
|
||||
f" Unshallowed via {try_remote}"
|
||||
)
|
||||
_logger.info(f" Unshallowed via {try_remote}")
|
||||
return
|
||||
if os.path.exists(shallow_file):
|
||||
_logger.warning(
|
||||
|
|
@ -585,30 +543,22 @@ async def _push_single_repo(
|
|||
):
|
||||
"""Push a single repo to local remote (async)."""
|
||||
async with semaphore:
|
||||
repo_path = os.path.join(
|
||||
erplibre_root, project["path"]
|
||||
)
|
||||
repo_path = os.path.join(erplibre_root, project["path"])
|
||||
if not os.path.isdir(repo_path):
|
||||
_logger.warning(f" Not found: {repo_path}")
|
||||
return "error", False
|
||||
|
||||
# Handle shallow repos
|
||||
shallow_file = os.path.join(
|
||||
repo_path, ".git", "shallow"
|
||||
)
|
||||
shallow_file = os.path.join(repo_path, ".git", "shallow")
|
||||
if os.path.exists(shallow_file):
|
||||
if unshallow:
|
||||
await _try_unshallow(
|
||||
repo_path, project, remote_name
|
||||
)
|
||||
await _try_unshallow(repo_path, project, remote_name)
|
||||
else:
|
||||
# Enable shallow push on bare repo
|
||||
repo_name = project["name"]
|
||||
if not repo_name.endswith(".git"):
|
||||
repo_name += ".git"
|
||||
bare_path = os.path.join(
|
||||
git_path, repo_name
|
||||
)
|
||||
bare_path = os.path.join(git_path, repo_name)
|
||||
if os.path.isdir(bare_path):
|
||||
await _run_git(
|
||||
"git",
|
||||
|
|
@ -618,19 +568,14 @@ async def _push_single_repo(
|
|||
"receive.shallowUpdate",
|
||||
"true",
|
||||
)
|
||||
_logger.info(
|
||||
f" Shallow push for"
|
||||
f" {project['path']}"
|
||||
)
|
||||
_logger.info(f" Shallow push for" f" {project['path']}")
|
||||
|
||||
# Handle detached HEAD: checkout manifest branch
|
||||
did_checkout = False
|
||||
if await _is_detached_head(repo_path):
|
||||
revision = project.get("revision", "")
|
||||
if revision:
|
||||
branch = await _checkout_manifest_branch(
|
||||
repo_path, revision
|
||||
)
|
||||
branch = await _checkout_manifest_branch(repo_path, revision)
|
||||
_logger.info(
|
||||
f" Checkout {branch} for"
|
||||
f" {project['path']}"
|
||||
|
|
@ -663,9 +608,7 @@ async def _push_single_repo(
|
|||
"push",
|
||||
remote_name,
|
||||
]
|
||||
_, err, rc = await _run_git(
|
||||
*cmd, timeout=120
|
||||
)
|
||||
_, err, rc = await _run_git(*cmd, timeout=120)
|
||||
if rc != 0:
|
||||
_logger.warning(
|
||||
f" Push failed for"
|
||||
|
|
@ -675,14 +618,10 @@ async def _push_single_repo(
|
|||
return "error", did_checkout
|
||||
else:
|
||||
await _update_bare_head(git_path, project)
|
||||
_logger.info(
|
||||
f" Pushed: {project['path']}"
|
||||
)
|
||||
_logger.info(f" Pushed: {project['path']}")
|
||||
return "pushed", did_checkout
|
||||
except asyncio.TimeoutError:
|
||||
_logger.warning(
|
||||
f" Timeout pushing {project['path']}"
|
||||
)
|
||||
_logger.warning(f" Timeout pushing {project['path']}")
|
||||
return "error", did_checkout
|
||||
|
||||
|
||||
|
|
@ -744,8 +683,7 @@ def print_clone_commands(git_path, projects, port):
|
|||
if clone_path == ".":
|
||||
clone_path = "erplibre"
|
||||
lines.append(
|
||||
f" git clone {base_url}/{repo_name}"
|
||||
f" {clone_path}"
|
||||
f" git clone {base_url}/{repo_name}" f" {clone_path}"
|
||||
)
|
||||
lines.sort()
|
||||
for line in lines:
|
||||
|
|
|
|||
|
|
@ -26,17 +26,10 @@ def get_pull_request_repo(
|
|||
parsed_url = parse(upstream_url)
|
||||
|
||||
status, user = gh.user.get()
|
||||
user_name = (
|
||||
user["login"] if not organization_name else organization_name
|
||||
)
|
||||
status, lst_pull = (
|
||||
gh.repos[user_name][parsed_url.repo].pulls.get()
|
||||
)
|
||||
user_name = user["login"] if not organization_name else organization_name
|
||||
status, lst_pull = gh.repos[user_name][parsed_url.repo].pulls.get()
|
||||
if type(lst_pull) is dict:
|
||||
print(
|
||||
f"For url {upstream_url},"
|
||||
f" got {lst_pull.get('message')}"
|
||||
)
|
||||
print(f"For url {upstream_url}," f" got {lst_pull.get('message')}")
|
||||
return False
|
||||
else:
|
||||
for pull in lst_pull:
|
||||
|
|
@ -53,26 +46,21 @@ def fork_repo(
|
|||
parsed_url = parse(upstream_url)
|
||||
|
||||
status, user = gh.user.get()
|
||||
user_name = (
|
||||
user["login"] if not organization_name else organization_name
|
||||
)
|
||||
status, forked_repo = (
|
||||
gh.repos[user_name][parsed_url.repo].get()
|
||||
)
|
||||
user_name = user["login"] if not organization_name else organization_name
|
||||
status, forked_repo = gh.repos[user_name][parsed_url.repo].get()
|
||||
if status == 404:
|
||||
status, upstream_repo = (
|
||||
gh.repos[parsed_url.owner][parsed_url.repo].get()
|
||||
)
|
||||
status, upstream_repo = gh.repos[parsed_url.owner][
|
||||
parsed_url.repo
|
||||
].get()
|
||||
if status == 404:
|
||||
print("Unable to find repo %s" % upstream_url)
|
||||
exit(1)
|
||||
args = {}
|
||||
if organization_name:
|
||||
args["organization"] = organization_name
|
||||
status, forked_repo = (
|
||||
gh.repos[parsed_url.owner][parsed_url.repo]
|
||||
.forks.post(**args)
|
||||
)
|
||||
status, forked_repo = gh.repos[parsed_url.owner][
|
||||
parsed_url.repo
|
||||
].forks.post(**args)
|
||||
if status == 404:
|
||||
print(
|
||||
f"{Fore.RED}Error{Style.RESET_ALL} when forking"
|
||||
|
|
@ -82,23 +70,16 @@ def fork_repo(
|
|||
else:
|
||||
try:
|
||||
print(
|
||||
"Forked %s to %s"
|
||||
% (upstream_url, forked_repo["html_url"])
|
||||
"Forked %s to %s" % (upstream_url, forked_repo["html_url"])
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(forked_repo)
|
||||
print(upstream_url)
|
||||
elif status == 202:
|
||||
print(
|
||||
"Forked repo %s already exists"
|
||||
% forked_repo["full_name"]
|
||||
)
|
||||
print("Forked repo %s already exists" % forked_repo["full_name"])
|
||||
elif status != 200:
|
||||
print(
|
||||
"Status not supported: %s - %s"
|
||||
% (status, forked_repo)
|
||||
)
|
||||
print("Status not supported: %s - %s" % (status, forked_repo))
|
||||
exit(1)
|
||||
|
||||
|
||||
|
|
@ -110,9 +91,7 @@ def add_and_fetch_remote(
|
|||
"""
|
||||
try:
|
||||
working_repo = Repo(repo_info.relative_path)
|
||||
if repo_info.organization in [
|
||||
a.name for a in working_repo.remotes
|
||||
]:
|
||||
if repo_info.organization in [a.name for a in working_repo.remotes]:
|
||||
print(
|
||||
f'Remote "{repo_info.organization}" already exist'
|
||||
f" in {repo_info.relative_path}"
|
||||
|
|
@ -122,8 +101,7 @@ def add_and_fetch_remote(
|
|||
print(f"New repo {repo_info.relative_path}")
|
||||
if not root_repo:
|
||||
print(
|
||||
"Missing git repository to root for repo"
|
||||
f" {repo_info.path}"
|
||||
"Missing git repository to root for repo" f" {repo_info.path}"
|
||||
)
|
||||
return
|
||||
if branch_name:
|
||||
|
|
@ -149,16 +127,14 @@ def add_and_fetch_remote(
|
|||
# Add remote
|
||||
upstream_remote = retry(
|
||||
wait_exponential_multiplier=1000, stop_max_delay=15000
|
||||
)(working_repo.create_remote)(
|
||||
repo_info.organization, repo_info.url_https
|
||||
)
|
||||
)(working_repo.create_remote)(repo_info.organization, repo_info.url_https)
|
||||
print(
|
||||
'Remote "%s" created for %s'
|
||||
% (repo_info.organization, repo_info.url_https)
|
||||
)
|
||||
|
||||
# Fetch the remote
|
||||
retry(
|
||||
wait_exponential_multiplier=1000, stop_max_delay=15000
|
||||
)(upstream_remote.fetch)()
|
||||
retry(wait_exponential_multiplier=1000, stop_max_delay=15000)(
|
||||
upstream_remote.fetch
|
||||
)()
|
||||
print('Remote "%s" fetched' % repo_info.organization)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ _logger = logging.getLogger(__name__)
|
|||
|
||||
PROJECT_NAME = os.path.basename(os.getcwd())
|
||||
IDEA_PATH = "./.idea"
|
||||
DEFAULT_ODOO_BIN = "./odoo/odoo-bin" # Need this to replace static configuration
|
||||
DEFAULT_ODOO_BIN = (
|
||||
"./odoo/odoo-bin" # Need this to replace static configuration
|
||||
)
|
||||
IDEA_MISC = os.path.join(IDEA_PATH, "misc.xml")
|
||||
IDEA_WORKSPACE = os.path.join(IDEA_PATH, "workspace.xml")
|
||||
VCS_WORKSPACE = os.path.join(IDEA_PATH, "vcs.xml")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
installed_modules = env["ir.module.module"].search([('state', '=', 'installed')])
|
||||
installed_modules = env["ir.module.module"].search(
|
||||
[("state", "=", "installed")]
|
||||
)
|
||||
|
||||
print("Installed modules:")
|
||||
|
||||
|
|
|
|||
|
|
@ -10,18 +10,20 @@ print("Running a script in the Odoo shell!")
|
|||
# ERROR: insert or update on table "discuss_channel_member" violates foreign key constraint "discuss_channel_member_channel_id_fkey"
|
||||
# DÉTAIL : Key (channel_id)=(3) is not present in table "discuss_channel".
|
||||
|
||||
env.cr.execute("""
|
||||
env.cr.execute(
|
||||
"""
|
||||
ALTER TABLE discuss_channel
|
||||
DROP CONSTRAINT discuss_channel_channel_type_not_null;
|
||||
""")
|
||||
"""
|
||||
)
|
||||
env.cr.commit()
|
||||
|
||||
#env.cr.execute("SELECT to_regclass('public.discuss_channel');")
|
||||
#print("table:", env.cr.fetchone())
|
||||
# env.cr.execute("SELECT to_regclass('public.discuss_channel');")
|
||||
# print("table:", env.cr.fetchone())
|
||||
|
||||
#print(
|
||||
# print(
|
||||
# "model discuss.channel:",
|
||||
# env["ir.model"].search([("model", "=", "discuss.channel")]),
|
||||
#)
|
||||
# )
|
||||
|
||||
print("End fix migration with update mail postgresql 17 to postgresql 18.")
|
||||
|
|
|
|||
|
|
@ -393,7 +393,9 @@ class TODO:
|
|||
odoo_version_input = ""
|
||||
while odoo_version_input not in install_commands:
|
||||
if odoo_version_input:
|
||||
print(f"{t('Error, cannot understand value')} '{odoo_version_input}'")
|
||||
print(
|
||||
f"{t('Error, cannot understand value')} '{odoo_version_input}'"
|
||||
)
|
||||
str_input_dyn_odoo_version = (
|
||||
f"💬 {t('Choose a version:')}\n\t"
|
||||
+ "\n\t".join([a[1] for a in install_commands.values()])
|
||||
|
|
@ -417,7 +419,9 @@ class TODO:
|
|||
cmd_intern, shell=True, executable="/bin/bash", check=True
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"{t('The Bash script failed with return code')} {e.returncode}.")
|
||||
print(
|
||||
f"{t('The Bash script failed with return code')} {e.returncode}."
|
||||
)
|
||||
print("Wait after installation and open projects by terminal.")
|
||||
print("make open_terminal")
|
||||
self.restart_script(str(e))
|
||||
|
|
@ -464,9 +468,7 @@ class TODO:
|
|||
bash_command = instance.get("bash_command")
|
||||
if bash_command:
|
||||
print(f"{t('Will execute:')} {bash_command}")
|
||||
self.execute.exec_command_live(
|
||||
bash_command, source_erplibre=False
|
||||
)
|
||||
self.execute.exec_command_live(bash_command, source_erplibre=False)
|
||||
|
||||
command = instance.get("Command:")
|
||||
if command:
|
||||
|
|
@ -525,7 +527,9 @@ class TODO:
|
|||
int_cmd = int(status)
|
||||
if 1 < int_cmd <= init_len:
|
||||
cmd_no_found = False
|
||||
status = click.confirm(t("Do you want a new instance?"))
|
||||
status = click.confirm(
|
||||
t("Do you want a new instance?")
|
||||
)
|
||||
instance = choices[int_cmd - 1]
|
||||
self.execute_from_configuration(
|
||||
instance,
|
||||
|
|
@ -612,15 +616,9 @@ class TODO:
|
|||
print(t("Command not found !"))
|
||||
|
||||
def prompt_execute_deploy(self):
|
||||
print(
|
||||
f"🤖 {t('Deploy ERPLibre to a local directory!')}"
|
||||
)
|
||||
print(f"🤖 {t('Deploy ERPLibre to a local directory!')}")
|
||||
choices = [
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Clone ERPLibre locally (git clone)"
|
||||
)
|
||||
},
|
||||
{"prompt_description": t("Clone ERPLibre locally (git clone)")},
|
||||
]
|
||||
help_info = self.fill_help_info(choices)
|
||||
|
||||
|
|
@ -637,16 +635,12 @@ class TODO:
|
|||
def _deploy_clone_erplibre(self):
|
||||
default_path = os.path.expanduser("~/erplibre")
|
||||
target_path = (
|
||||
input(
|
||||
t("Target directory path (default: ~/erplibre): ")
|
||||
).strip()
|
||||
input(t("Target directory path (default: ~/erplibre): ")).strip()
|
||||
or default_path
|
||||
)
|
||||
target_path = os.path.expanduser(target_path)
|
||||
if os.path.exists(target_path):
|
||||
print(
|
||||
f"{t('Directory already exists: ')}{target_path}"
|
||||
)
|
||||
print(f"{t('Directory already exists: ')}{target_path}")
|
||||
return
|
||||
print(t("Cloning ERPLibre..."))
|
||||
cmd = (
|
||||
|
|
@ -656,13 +650,8 @@ class TODO:
|
|||
)
|
||||
print(f"{t('Will execute:')} {cmd}")
|
||||
try:
|
||||
self.execute.exec_command_live(
|
||||
cmd, source_erplibre=False
|
||||
)
|
||||
print(
|
||||
f"{t('ERPLibre cloned successfully to: ')}"
|
||||
f"{target_path}"
|
||||
)
|
||||
self.execute.exec_command_live(cmd, source_erplibre=False)
|
||||
print(f"{t('ERPLibre cloned successfully to: ')}" f"{target_path}")
|
||||
except Exception as e:
|
||||
print(f"{t('Error cloning ERPLibre: ')}{e}")
|
||||
|
||||
|
|
@ -762,18 +751,19 @@ class TODO:
|
|||
|
||||
def _git_add_remote(self):
|
||||
remote_name = (
|
||||
input(t("Remote name (default: localhost): ")).strip() or "localhost"
|
||||
input(t("Remote name (default: localhost): ")).strip()
|
||||
or "localhost"
|
||||
)
|
||||
remote_url = input(t("Repository address (e.g.: git://192.168.1.100/my-repo.git): ")).strip()
|
||||
remote_url = input(
|
||||
t("Repository address (e.g.: git://192.168.1.100/my-repo.git): ")
|
||||
).strip()
|
||||
if not remote_url:
|
||||
print(t("Repository address is required!"))
|
||||
return
|
||||
cmd = f"git remote add {remote_name} {remote_url}"
|
||||
print(f"{t('Will execute:')} {cmd}")
|
||||
try:
|
||||
self.execute.exec_command_live(
|
||||
cmd, source_erplibre=False
|
||||
)
|
||||
self.execute.exec_command_live(cmd, source_erplibre=False)
|
||||
print(t("Remote added successfully!"))
|
||||
except Exception as e:
|
||||
print(f"{t('Error adding remote: ')}{e}")
|
||||
|
|
@ -781,8 +771,16 @@ class TODO:
|
|||
def prompt_execute_git_local_server(self):
|
||||
print(f"🤖 {t('Manage local git repository server!')}")
|
||||
choices = [
|
||||
{"prompt_description": t("Deploy a local git server (~/.git-server)")},
|
||||
{"prompt_description": t("Deploy a production git server (/srv/git, root required)")},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Deploy a local git server (~/.git-server)"
|
||||
)
|
||||
},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Deploy a production git server (/srv/git, root required)"
|
||||
)
|
||||
},
|
||||
]
|
||||
help_info = self.fill_help_info(choices)
|
||||
|
||||
|
|
@ -806,7 +804,11 @@ class TODO:
|
|||
)
|
||||
print(f"🤖 {mode}")
|
||||
choices = [
|
||||
{"prompt_description": t("Run all (init + remote + push + serve)")},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Run all (init + remote + push + serve)"
|
||||
)
|
||||
},
|
||||
{"prompt_description": t("Init - Create bare repos")},
|
||||
{"prompt_description": t("Remote - Add local remotes")},
|
||||
{"prompt_description": t("Push - Push to local server")},
|
||||
|
|
@ -863,8 +865,16 @@ class TODO:
|
|||
print(f"🤖 {t('AI assistant tools for development!')}")
|
||||
choices = [
|
||||
{"prompt_description": t("Configure Claude Code configurations")},
|
||||
{"prompt_description": t("Add an automation with Claude in todo.py")},
|
||||
{"prompt_description": t("RTK - CLI proxy to reduce LLM token consumption")},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Add an automation with Claude in todo.py"
|
||||
)
|
||||
},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"RTK - CLI proxy to reduce LLM token consumption"
|
||||
)
|
||||
},
|
||||
]
|
||||
help_info = self.fill_help_info(choices)
|
||||
|
||||
|
|
@ -891,11 +901,7 @@ class TODO:
|
|||
"Todo Add Command - Add a command to todo.py menu"
|
||||
)
|
||||
},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Show installed custom commands"
|
||||
)
|
||||
},
|
||||
{"prompt_description": t("Show installed custom commands")},
|
||||
]
|
||||
help_info = self.fill_help_info(choices)
|
||||
|
||||
|
|
@ -926,9 +932,7 @@ class TODO:
|
|||
print(t("No custom commands found in ~/.claude/commands/"))
|
||||
return
|
||||
files = sorted(
|
||||
f
|
||||
for f in os.listdir(commands_dir)
|
||||
if f.endswith(".md")
|
||||
f for f in os.listdir(commands_dir) if f.endswith(".md")
|
||||
)
|
||||
if not files:
|
||||
print(t("No custom commands found in ~/.claude/commands/"))
|
||||
|
|
@ -944,10 +948,7 @@ class TODO:
|
|||
name = f[:-3] # remove .md
|
||||
print(f" /{name:<30} {date_str}")
|
||||
print("-" * 50)
|
||||
print(
|
||||
f"{t('Total:')}"
|
||||
f" {len(files)}"
|
||||
)
|
||||
print(f"{t('Total:')}" f" {len(files)}")
|
||||
|
||||
def _setup_claude_command(
|
||||
self, command_name, template_filename, personalize=False
|
||||
|
|
@ -996,14 +997,10 @@ class TODO:
|
|||
print(f"{t('Error creating file: ')}{e}")
|
||||
|
||||
def _claude_add_automation(self):
|
||||
description = input(
|
||||
t("Description of the command to add: ")
|
||||
).strip()
|
||||
description = input(t("Description of the command to add: ")).strip()
|
||||
if not description:
|
||||
return
|
||||
command = input(
|
||||
t("Bash command to execute: ")
|
||||
).strip()
|
||||
command = input(t("Bash command to execute: ")).strip()
|
||||
if not command:
|
||||
return
|
||||
section = (
|
||||
|
|
@ -1013,9 +1010,7 @@ class TODO:
|
|||
or "git"
|
||||
)
|
||||
section_key = f"{section}_from_makefile"
|
||||
config_path = os.path.join(
|
||||
os.path.dirname(__file__), "todo.json"
|
||||
)
|
||||
config_path = os.path.join(os.path.dirname(__file__), "todo.json")
|
||||
try:
|
||||
with open(config_path) as f:
|
||||
config = json.load(f)
|
||||
|
|
@ -1086,7 +1081,11 @@ class TODO:
|
|||
def prompt_execute_database(self):
|
||||
print(f"🤖 {t('Make changes to databases!')}")
|
||||
choices = [
|
||||
{"prompt_description": t("Download database to create backup (.zip)")},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Download database to create backup (.zip)"
|
||||
)
|
||||
},
|
||||
{"prompt_description": t("Restore from backup (.zip)")},
|
||||
{"prompt_description": t("Create backup (.zip)")},
|
||||
]
|
||||
|
|
@ -1134,7 +1133,9 @@ class TODO:
|
|||
print(t("Git daemon process killed."))
|
||||
|
||||
def prompt_execute_rtk(self):
|
||||
print(f"🤖 {t('Manage RTK (Rust Token Killer) for token optimization!')}")
|
||||
print(
|
||||
f"🤖 {t('Manage RTK (Rust Token Killer) for token optimization!')}"
|
||||
)
|
||||
choices = [
|
||||
{"prompt_description": t("Install RTK")},
|
||||
{"prompt_description": t("Check RTK version")},
|
||||
|
|
@ -1170,7 +1171,11 @@ class TODO:
|
|||
choices = [
|
||||
{"prompt_description": t("curl - Automatic install script")},
|
||||
{"prompt_description": t("brew - Homebrew (macOS/Linux)")},
|
||||
{"prompt_description": t("cargo - Build from source (Rust required)")},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"cargo - Build from source (Rust required)"
|
||||
)
|
||||
},
|
||||
]
|
||||
help_info = self.fill_help_info(choices)
|
||||
status = click.prompt(help_info)
|
||||
|
|
@ -1323,7 +1328,11 @@ class TODO:
|
|||
def prompt_execute_security(self):
|
||||
print(f"🤖 {t('Dependency security audit!')}")
|
||||
choices = [
|
||||
{"prompt_description": t("pip-audit - Check vulnerabilities on Python environments")},
|
||||
{
|
||||
"prompt_description": t(
|
||||
"pip-audit - Check vulnerabilities on Python environments"
|
||||
)
|
||||
},
|
||||
]
|
||||
help_info = self.fill_help_info(choices)
|
||||
|
||||
|
|
@ -1368,12 +1377,16 @@ class TODO:
|
|||
return
|
||||
|
||||
# Database name
|
||||
db_name = input(t("Temporary database name (default: test_todo_tmp): ")).strip()
|
||||
db_name = input(
|
||||
t("Temporary database name (default: test_todo_tmp): ")
|
||||
).strip()
|
||||
if not db_name:
|
||||
db_name = "test_todo_tmp"
|
||||
|
||||
# Extra modules
|
||||
extra_modules = input(t("Extra modules to install (comma-separated, empty for none): ")).strip()
|
||||
extra_modules = input(
|
||||
t("Extra modules to install (comma-separated, empty for none): ")
|
||||
).strip()
|
||||
|
||||
# Log level
|
||||
log_level = input(t("Log level (default: test): ")).strip()
|
||||
|
|
@ -1395,9 +1408,7 @@ class TODO:
|
|||
)
|
||||
|
||||
# Step 2: Install modules
|
||||
print(
|
||||
f"\n--- {t('Installing modules')}: {modules_to_install} ---"
|
||||
)
|
||||
print(f"\n--- {t('Installing modules')}: {modules_to_install} ---")
|
||||
cmd_install = (
|
||||
f"./script/addons/install_addons.sh"
|
||||
f" {db_name} {modules_to_install}"
|
||||
|
|
@ -1433,12 +1444,16 @@ class TODO:
|
|||
|
||||
# Step 4: Cleanup
|
||||
lang = get_lang()
|
||||
keep_input = input(t("Keep the temporary database? (y/N): ")).strip().lower()
|
||||
keep_input = (
|
||||
input(t("Keep the temporary database? (y/N): ")).strip().lower()
|
||||
)
|
||||
keep = keep_input in (("o", "oui") if lang == "fr" else ("y", "yes"))
|
||||
if keep:
|
||||
print(f"{t('Database kept')}: {db_name}")
|
||||
else:
|
||||
print(f"\n--- {t('Cleaning up temporary database')} '{db_name}' ---")
|
||||
print(
|
||||
f"\n--- {t('Cleaning up temporary database')} '{db_name}' ---"
|
||||
)
|
||||
cmd_drop = f"./odoo_bin.sh db --drop --database {db_name}"
|
||||
self.execute.exec_command_live(
|
||||
cmd_drop,
|
||||
|
|
@ -1460,7 +1475,9 @@ class TODO:
|
|||
if status_code == 0:
|
||||
print(f"\n✅ {t('All unit tests passed')}")
|
||||
else:
|
||||
print(f"\n❌ {t('Some unit tests failed, exit code')}: {status_code}")
|
||||
print(
|
||||
f"\n❌ {t('Some unit tests failed, exit code')}: {status_code}"
|
||||
)
|
||||
|
||||
def execute_pip_audit(self):
|
||||
versions, installed_versions, odoo_installed_version = (
|
||||
|
|
@ -1495,7 +1512,11 @@ class TODO:
|
|||
}
|
||||
|
||||
if not environments:
|
||||
print(t("No installed environment found. Install an Odoo version first."))
|
||||
print(
|
||||
t(
|
||||
"No installed environment found. Install an Odoo version first."
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
# Show selection menu
|
||||
|
|
@ -1508,7 +1529,9 @@ class TODO:
|
|||
env_input = ""
|
||||
while env_input not in environments and env_input != "0":
|
||||
if env_input:
|
||||
print(f"{t('Error, cannot understand value')}" f" '{env_input}'")
|
||||
print(
|
||||
f"{t('Error, cannot understand value')}" f" '{env_input}'"
|
||||
)
|
||||
env_input = input(str_input).strip()
|
||||
|
||||
if env_input == "0":
|
||||
|
|
|
|||
Loading…
Reference in a new issue