Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions lib/devbase/cli.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -242,6 +242,21 @@ def _add_project_parser(subparsers):
# 取らない (wrapper の _PROJECT_NAME_SUBCOMMANDS にも含めない)。
_add_list_subparser(pj_sub)

# `migrate-config` は旧 env 形式から project.yml への変換 (PLAN32)。lifecycle
# ではないため wrapper の _PROJECT_NAME_SUBCOMMANDS には含めない。
pj_migrate = pj_sub.add_parser(
'migrate-config',
help='Convert legacy env (GIT_USER/GIT_REPO/...) into project.yml')
pj_migrate.add_argument('names', nargs='*', metavar='NAME',
help='Limit to the given projects (default: all)')
pj_migrate.add_argument('--dry-run', action='store_true',
help='Show what would change without writing')
# plugin リポジトリには devbase へリンクしていない projects/ もある
# (`repos/<repo>/<plugin>/projects`)。一括移行のため直接指定できるようにする。
pj_migrate.add_argument('--projects-dir', metavar='DIR', default=None,
help='Directory holding the projects '
'(default: $DEVBASE_ROOT/projects)')


def _add_list_subparser(sub):
"""`list` サブコマンドを登録する (project list / top-level list 共通)。
Expand DownExpand Up@@ -762,6 +777,11 @@ def _dispatch(cmd, args):
devbase_root = _require_devbase_root()
from devbase.commands.project import cmd_project_list
return cmd_project_list(devbase_root, args)
# `project migrate-config` も lifecycle ではなく projects/ 全体の変換。
if getattr(args, 'subcommand', None) == 'migrate-config':
devbase_root = _require_devbase_root()
from devbase.commands.project import cmd_project_migrate_config
return cmd_project_migrate_config(devbase_root, args)
from devbase.commands.container import cmd_project
return cmd_project(args)

Expand Down
54 changes: 54 additions & 0 deletions lib/devbase/commands/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
from __future__ import annotations

import os
import sys
from pathlib import Path

from devbase.log import get_logger
Expand DownExpand Up@@ -169,3 +170,56 @@ def cmd_project_list(devbase_root: Path, args) -> int:
from devbase.tui import run as tui_run

return tui_run(Path(devbase_root), args)


def cmd_project_migrate_config(devbase_root: Path, args) -> int:
"""`devbase project migrate-config [name...] [--dry-run]` (PLAN32)。

旧 ``env`` 形式 (``GIT_USER`` / ``GIT_REPO`` 等) を ``project.yml`` へ変換する。
``projects/<name>`` は plugin リポジトリへの symlink なので、書き換わるのは
plugin リポジトリ側の実体ファイルになる。どのパスを触ったかを必ず表示する。

``--projects-dir`` で別のディレクトリを指定できる。plugin リポジトリには
devbase へリンクしていない projects (``repos/<repo>/<plugin>/projects``) も
あり、それらを一括で移行するため。
"""
from devbase.project.migrate import migrate_project, migrate_projects

override = getattr(args, 'projects_dir', None)
projects_dir = Path(override) if override else Path(devbase_root) / 'projects'
if not projects_dir.is_dir():
print(f"projects ディレクトリがありません: {projects_dir}", file=sys.stderr)
return 1

names = list(getattr(args, 'names', None) or [])
dry_run = bool(getattr(args, 'dry_run', False))

if names:
missing = [name for name in names if not (projects_dir / name).is_dir()]
if missing:
print(f"プロジェクトが見つかりません: {', '.join(missing)}",
file=sys.stderr)
return 1
results = [migrate_project(projects_dir / name, dry_run=dry_run)
for name in names]
else:
results = migrate_projects(projects_dir, dry_run=dry_run)

if dry_run:
print("=== dry-run: ファイルは書き換えません ===")

counts = {}
for result in results:
counts[result.status] = counts.get(result.status, 0) + 1
detail = f" — {result.reason}" if result.reason else ""
print(f"[{result.status}] {result.name} ({result.path}){detail}")
if dry_run and result.project_yml:
print(_indent(result.project_yml))

print("--- " + " / ".join(f"{status}={count}"
for status, count in sorted(counts.items())))
return 1 if counts.get('failed') else 0


def _indent(text: str, prefix: str = ' ') -> str:
return ''.join(prefix + line + '\n' for line in text.splitlines())
Loading