|
13 | 13 |
|
14 | 14 | from lemoncrow.gateway.cli.commands._shared import _emit, require_pro |
15 | 15 | from lemoncrow.gateway.integrations.openmemory_lifecycle import project_root as _project_root |
16 | | -from lemoncrow.infra.code_intel.portable import TIERS as _PORTABLE_TIERS |
17 | 16 |
|
18 | 17 |
|
19 | 18 | @click.group("zoekt") |
@@ -823,76 +822,14 @@ def _entry_age_days(entry: Path, now: float) -> float: |
823 | 822 | return max(0.0, (now - newest) / 86_400.0) |
824 | 823 |
|
825 | 824 |
|
826 | | -def _portable_repo_root(repo_root: str | None) -> Path: |
| 825 | +def _resolve_repo_root(repo_root: str | None) -> Path: |
827 | 826 | if repo_root is not None: |
828 | 827 | return Path(repo_root).expanduser().resolve() |
829 | 828 | from lemoncrow.core.foundation.paths import resolve_workspace_root |
830 | 829 |
|
831 | 830 | return Path(resolve_workspace_root()).resolve() |
832 | 831 |
|
833 | 832 |
|
834 | | -@code_group.command("export") |
835 | | -@click.option( |
836 | | - "--out", default=None, type=click.Path(path_type=Path), help="Archive path (default: .lemoncrow/index.tar.*)." |
837 | | -) |
838 | | -@click.option( |
839 | | - "--tier", |
840 | | - type=click.Choice(sorted(_PORTABLE_TIERS)), |
841 | | - default="best", |
842 | | - show_default=True, |
843 | | - help="best: smaller archive, slower. fast: quicker, for incremental refresh.", |
844 | | -) |
845 | | -@click.option("--repo-root", default=None, help="Repository root (default: the resolved workspace root).") |
846 | | -@click.option("--json", "as_json", is_flag=True) |
847 | | -def code_export_cmd(out: Path | None, tier: str, repo_root: str | None, as_json: bool) -> None: |
848 | | - """Pack this workspace's code index into a portable archive. |
849 | | -
|
850 | | - Compacts each database, records the engine's index and semantics versions |
851 | | - in a manifest, and compresses the bundle. The archive is deliberately not |
852 | | - committed anywhere by default -- it is a build artifact, not source. |
853 | | - """ |
854 | | - from lemoncrow.infra.code_intel.portable import PortableIndexError, export_index |
855 | | - |
856 | | - try: |
857 | | - result = export_index(repo_root=_portable_repo_root(repo_root), out=out, tier=tier) |
858 | | - except PortableIndexError as exc: |
859 | | - raise click.ClickException(str(exc)) from exc |
860 | | - if as_json: |
861 | | - _emit(result.to_dict(), as_json=True) |
862 | | - return |
863 | | - click.echo(f"Wrote {result.path} ({result.size_bytes:,} bytes, {result.codec}, tier={result.tier})") |
864 | | - click.echo(f" databases: {', '.join(result.databases)}") |
865 | | - click.echo(f" engine index_version: {result.manifest['engine_index_version']}") |
866 | | - |
867 | | - |
868 | | -@code_group.command("import") |
869 | | -@click.option("--from", "source", required=True, type=click.Path(path_type=Path), help="Archive to import.") |
870 | | -@click.option("--repo-root", default=None, help="Repository root (default: the resolved workspace root).") |
871 | | -@click.option("--force", is_flag=True, help="Replace an index this workspace already holds.") |
872 | | -@click.option("--json", "as_json", is_flag=True) |
873 | | -def code_import_cmd(source: Path, repo_root: str | None, force: bool, as_json: bool) -> None: |
874 | | - """Restore a code index from an archive built by `lc code export`. |
875 | | -
|
876 | | - Refuses on an indexer-semantics mismatch. The engine owns that number and |
877 | | - open code cannot migrate its data, so importing across it would produce a |
878 | | - graph whose edges mean something else -- confident and wrong. Re-index |
879 | | - instead. --force overrides only the already-populated check. |
880 | | - """ |
881 | | - from lemoncrow.infra.code_intel.portable import PortableIndexError, import_index |
882 | | - |
883 | | - try: |
884 | | - result = import_index(archive=source, repo_root=_portable_repo_root(repo_root), force=force) |
885 | | - except PortableIndexError as exc: |
886 | | - raise click.ClickException(str(exc)) from exc |
887 | | - if as_json: |
888 | | - _emit(result.to_dict(), as_json=True) |
889 | | - return |
890 | | - click.echo(f"Restored {len(result.restored)} database(s) into {result.workspace}") |
891 | | - click.echo(f" from: {result.archive}") |
892 | | - click.echo(f" verified against: {result.verified_against}") |
893 | | - click.echo("Run `lc code index` to fill in the local diff.") |
894 | | - |
895 | | - |
896 | 833 | @code_group.command("clones") |
897 | 834 | @click.option( |
898 | 835 | "--threshold", |
@@ -938,14 +875,13 @@ def code_clones_cmd( |
938 | 875 |
|
939 | 876 | try: |
940 | 877 | report = build_clones( |
941 | | - repo_root=_portable_repo_root(repo_root), |
| 878 | + repo_root=_resolve_repo_root(repo_root), |
942 | 879 | threshold=DEFAULT_THRESHOLD if threshold is None else threshold, |
943 | 880 | min_tokens=MIN_TOKENS if min_tokens is None else min_tokens, |
944 | 881 | ) |
945 | 882 | except (CodeIntelUnavailable, IndexRebuilding) as exc: |
946 | | - # Matches `lc code export` / `import` above: an unindexed workspace, or |
947 | | - # one mid-reindex, is a thing the user can act on, so it gets a one-line |
948 | | - # message rather than a traceback. |
| 883 | + # An unindexed workspace, or one mid-reindex, is a thing the user can act |
| 884 | + # on, so it gets a one-line message rather than a traceback. |
949 | 885 | raise click.ClickException(str(exc)) from exc |
950 | 886 | if as_json: |
951 | 887 | _emit(report.as_dict(), as_json=True) |
|
0 commit comments