Metadata-Version: 2.4
Name: cola-cli
Version: 0.1.0
Summary: Global COLA environment and module manager for Linux and macOS
Author: Novikov Artemii
License-Expression: MIT
Keywords: cola,physics,cli,environment,package-manager
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click<9,>=8.1
Requires-Dist: jinja2<4,>=3.1
Requires-Dist: uv<1,>=0.9
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Requires-Dist: ruff>=0.9; extra == "test"
Requires-Dist: build; extra == "test"
Provides-Extra: release
Requires-Dist: build; extra == "release"
Requires-Dist: twine>=6; extra == "release"
Dynamic: license-file

# cola-cli

Standalone Python CLI for building and running COLA modules on **Linux and macOS**.
Installing the CLI does not compile COLA or import `colapy`.

This MVP has **one global environment per user**. Commands never search the current
directory for an environment. There are no project environments, named environments
or `--env` options. Completed build generations are internal revisions of that one
environment; only one is active at a time.

## Installation

Requires Python 3.11+:

```sh
python3 -m pip install cola-cli
cola --version
cola doctor
```

For an isolated CLI installation, use `pipx install cola-cli` or
`uv tool install cola-cli`. The managed COLA runtime is still the single global
environment described below.

From a local checkout:

```sh
python3 -m pip install /path/to/COLA-CLI
cola --version
cola doctor
```

The distribution is `cola-cli`, the import package is `cola_cli`, and the executable
is `cola`. `colapy` is installed separately inside the managed runtime. The updated
COLA-PY distribution uses `colapy` for its legacy executable to avoid overwriting
`cola`; `python -m colapy` remains available.

Install Git, CMake, Make and a C++17/20 compiler before building. Optional bridges
require a Fortran compiler, Julia 1.10+, or JDK 17+ respectively. Java filter projects
also need a Gradle Wrapper or Gradle. `uv` is a dependency of the CLI; Python packages
are resolved and installed by uv, Julia packages by Pkg, and Java dependencies by
Gradle. Native code uses the existing CMake projects.

The MVP uses explicitly selected native sources and existing external libraries.
It does **not** yet integrate Spack or automatically resolve/install external
scientific libraries such as Geant4 or ROOT. Provide existing native dependency
prefixes with `cola init --prefix /path/to/library` (repeatable).

## First calculation

```sh
# Local sources, including any uncommitted changes:
cola init --core /path/to/COLA --bindings /path/to/COLA-PY

# Or use upstream repositories. The first successful build records exact commits:
# cola init

cola add /path/to/MyPythonFilters
cola build
cola run --config calculation.xml --steps 10
```

`cola run` automatically loads the native libraries exported by the active modules,
including the language bridges. Repeat `--library NAME` to override that list. Python
filters must be installed as packages; the caller's `PYTHONPATH` and user site are not
used. The working directory is preserved for calculation data/configuration paths.

```sh
cola add github:org/MyPhysics --ref v1.2.0
cola add /path/to/MyRepository --subdirectory packages/MyPhysics
cola list
cola list --json
cola exec python -c 'import colapy; print(colapy.__version__)'
```

CMake applications can be managed too: declare `libraries = []` in their
`cola.toml`, list the required modules in `depends`, and provide a normal CMake
`install(TARGETS ... RUNTIME DESTINATION bin)` rule. Run installed executables with
`cola exec MyApplication ...`; the active native prefix's `bin` directory is on PATH.
For an example, see the `cola.toml` and installation rules in AAMCC-COLA.

`add` records the desired composition but does not replace the running environment.
It resolves Git refs to commits and snapshots local inputs. Non-locked builds take a
fresh snapshot of local sources; run `cola build` after editing a local module.
Local sources are copied, not installed editable, and builds do not modify checkouts.
Build outputs, `.git`, virtual environments and common caches are excluded.
Untracked build inputs are included. External symlinks and directory symlinks are
rejected because they cannot be represented by this snapshot format.
Modules must build from a source archive without requiring a live `.git` directory.

## Other languages

Add local bridges **before** their filter modules to use your checkouts:

```sh
cola add /path/to/COLA_Fortran
cola add /path/to/MyFortranFilters

cola add /path/to/COLA_JVM
cola add /path/to/MyJavaFilters

cola add /path/to/COLA_Julia
cola add /path/to/MyJuliaFilters

cola build
```

Missing standard bridges are added to the desired specification automatically using
their upstream Git repositories. To select a bridge version, explicitly add its Git
URL with `--ref`. Fortran and Java filter modules must expose their existing COLA
CMake integration. The Fortran port is currently CMake-based; fpm is not a backend in
this MVP. Julia packages use `Project.toml` and the COLA package UUID. Java projects
produce their runtime dependency JAR using their existing Gradle/CMake integration.

## Module metadata

`pyproject.toml`, `Project.toml` and `CMakeLists.txt` are detected automatically.
For a CMake module, the default native module name is the CMake project name.
Use `--library` if the installed COLA module has a different name.

An optional `cola.toml` makes the integration explicit:

```toml
[module]
name = "my-physics"
backend = "cmake"           # cmake, python or julia
depends = ["fortran"]       # module identifiers, not version expressions
libraries = ["MyPhysics"] # native directories under prefix/lib; [] for pure packages
cmake_args = ["-DENABLE_OPTION=ON"]
```

Dependencies remain in their native manifests. `depends` only orders explicitly
selected COLA modules; it is not a second dependency/version solver. The reserved
module identifiers are `core`, `python`, `fortran`, `java` and `julia`.
The MVP builds the core, Java/Fortran bridges, Julia packages, native filters, then
Python packages. Dependencies requiring the reverse phase order are rejected with
an explicit error; arbitrary cross-language build dependency cycles are unsupported.

CLI overrides are available for existing projects:

```sh
cola add /path/to/physics --name my-physics --backend cmake \
  --requires fortran --library MyPhysics --cmake-arg=-DENABLE_OPTION=ON
```

The scaffold generator is carried over from COLA-PY and adds `cola.toml`:

```sh
cola setup project --name MyPhysics --language python --prefix ./modules
```

Scaffolds contain declarations/stubs: implement them before adding and building.
C++ scaffolds must also define `LoadCOLAModule`, build a shared library and install
it under `lib/<module>`, as explained in their generated CMakeLists.

## Locks and updates

```sh
cola build                  # new local snapshots and language dependency resolution
cola sync --locked          # restore the active lock into a fresh generation
cola update my-physics      # follow that module's Git ref, resolve, build and activate
cola update                 # update all selected Git refs
cola remove my-physics      # edit desired composition
cola build                  # activate removal
```

Every successful build writes `current/cola.lock`. It records source SHA-256s,
Git commits, toolchain versions/flags, the uv project and lock, Julia's Project and
Manifest, Gradle dependency locks, and captured CMake FetchContent source trees.
Python build-system requirements are included in the uv environment; first-party
packages are then built with those backends using `--no-build-isolation`.
First-party Python packages therefore share one compatible set of build backends
in this MVP; mutually incompatible build-system requirements produce a uv error.

`sync --locked` requires unchanged desired composition and toolchain. It uses the
stored source snapshots even when the original local folder changed or was deleted.
It restores language locks and supplies captured FetchContent sources to CMake in
disconnected mode. Missing or modified snapshots cause an error. This is a
same-machine dependency/source lock, **not** a portable binary archive or a promise
of bit-identical output. System libraries, explicit external prefixes, arbitrary
downloads in custom build scripts, and Gradle plugin artifact contents are outside
the MVP's complete reproducibility guarantee. Do not use changing Maven SNAPSHOT
dependencies for locked builds.

## State and isolation

Default storage on both platforms is `~/.local/share/cola`. Set `COLA_HOME` to an
absolute location to move the **single** global store (also useful in CI):

```text
global.json               desired composition
sources/<sha256>/         stored source inputs
cache/uv/                 uv-managed dependency cache
generations/<id>/         prefix, Python venv, Julia project/depot, builds, build.log, cola.lock
current -> generations/id active completed build
```

Each build uses a new native prefix, Python venv and Julia environment. It is checked
by importing `colapy` and loading its declared native modules before an atomic pointer
switch. A failed build leaves the previous runtime active and retains its log.
Concurrent mutating commands are rejected. Running calculations keep using their
original physical generation. Old generations are deliberately retained in this MVP;
do not delete one while a calculation is using it. Runtime isolation is dependency
isolation, not a sandbox for third-party source/build scripts.

## Development and checks

```sh
python3 -m pip install -e '.[test]'
pytest
ruff check .
python3 -m build
```

Integration tests against real COLA repositories are opt-in:

```sh
COLA_CLI_CORE=/path/to/COLA COLA_CLI_BINDINGS=/path/to/COLA-PY pytest -m integration -v
```

The CI workflow runs the unit suite, wheel/resource checks and a real core/Python
build and locked restore on Linux and macOS. Optional bridge checks require their
corresponding compilers/runtimes and can be enabled with `COLA_CLI_PORTS` pointing to
the common parent directory of the four port checkouts.

## Publishing a release

The PyPI distribution name is `cola-cli`; the command remains `cola`. Version 0.1.0
is an alpha MVP. Increment `project.version` in `pyproject.toml` before every new
release. From the package directory, in a development virtual environment:

```sh
python -m pip install -e '.[test,release]'
ruff check src tests
pytest -m 'not integration'
# Use a fresh output directory to avoid uploading artifacts from older releases.
python -m build --outdir /tmp/cola-cli-release-0.1.0
python -m twine check --strict /tmp/cola-cli-release-0.1.0/*
python -m twine upload --repository pypi /tmp/cola-cli-release-0.1.0/*
```

Authenticate with a PyPI API token configured through Twine or `~/.pypirc`; never
commit tokens to the repository. Once the package has its own GitHub repository,
PyPI Trusted Publishing can replace the local token-based upload.
