# Unpac CLI Workflow ## Overview Unpac is a vendoring tool that lets you maintain local patches to dependencies while tracking upstream changes. This document describes the ideal CLI workflow. ## Quick Start ```bash # Initialize a new unpac workspace unpac init myworkspace cd myworkspace # Configure an opam repository unpac opam repo add opam-repository /path/to/opam-repository # Create a project unpac project new myapp # Add a dependency (looks up dev-repo in opam repository) unpac opam add cmdliner # Edit the vendored package (opens patches worktree) unpac opam edit cmdliner # ... make changes, e.g., port to dune ... cd opam/patches/cmdliner git add -A && git commit -m "Port cmdliner to dune" cd ../../.. # Add the patched package to your project unpac opam merge cmdliner myapp # Build your project cd project/myapp dune build ``` ## Commands ### Initialization #### `unpac init ` Initialize a new unpac workspace at the given path. ```bash unpac init myworkspace ``` Creates: - `git/` - bare git repository (shared object store) - `main/` - metadata branch with `unpac.toml` ### Project Management #### `unpac project new ` Create a new project branch. ```bash unpac project new myapp ``` Creates an orphan branch `project/` with: - `dune-project` with dune lang 3.20 - `dune` with `(vendored_dirs vendor)` - `vendor/opam/` directory structure #### `unpac project list` List all projects in the workspace. ```bash unpac project list ``` ### Opam Repository Management #### `unpac opam repo add ` Add an opam repository for package lookups. ```bash # Local repository unpac opam repo add opam-repository /workspace/opam/opam-repository # Remote repository (planned) unpac opam repo add opam-repository https://github.com/ocaml/opam-repository ``` #### `unpac opam repo list` List configured opam repositories. ```bash unpac opam repo list ``` #### `unpac opam repo remove ` Remove an opam repository. ```bash unpac opam repo remove opam-repository ``` ### Package Vendoring #### `unpac opam add [--name ] [--version ]` Vendor a package. Can specify either: - A package name (looks up dev-repo in configured repositories) - A git URL directly ```bash # By package name (recommended) unpac opam add cmdliner unpac opam add cmdliner --version 1.3.0 # By URL (for packages not in a repository) unpac opam add https://github.com/dbuenzli/cmdliner.git --name cmdliner ``` This creates three branches: - `opam/upstream/` - pristine upstream code - `opam/vendor/` - code with `vendor/opam//` path prefix - `opam/patches/` - your local modifications (initially same as vendor) #### `unpac opam list` List all vendored packages. ```bash unpac opam list ``` #### `unpac opam edit ` Open the patches worktree for editing a package. ```bash unpac opam edit cmdliner ``` Creates/checks out `opam/patches/cmdliner/` worktree. Make your changes there, then commit: ```bash cd opam/patches/cmdliner # ... edit files ... git add -A git commit -m "Port to dune build system" ``` #### `unpac opam done ` Close the patches worktree (cleanup after editing). ```bash unpac opam done cmdliner ``` #### `unpac opam update ` Update a package from upstream. ```bash unpac opam update cmdliner ``` This: 1. Fetches latest from upstream 2. Updates `opam/upstream/` and `opam/vendor/` 3. Prints instructions for rebasing patches if needed #### `unpac opam rebase ` Rebase your patches onto the updated vendor branch. ```bash unpac opam rebase cmdliner ``` Opens the patches worktree for conflict resolution if needed. #### `unpac opam merge ` Merge a vendored package into a project. ```bash unpac opam merge cmdliner myapp ``` Merges `opam/patches/` into `project/`, placing files under `vendor/opam//`. #### `unpac opam remove ` Remove a vendored package. ```bash unpac opam remove cmdliner ``` ### Package Information #### `unpac opam info ` Show information about a vendored package. ```bash unpac opam info cmdliner ``` Shows: - Upstream URL - Current upstream SHA - Current patches SHA - Number of local commits - Projects using this package #### `unpac opam diff ` Show the diff between vendor and patches (your local changes). ```bash unpac opam diff cmdliner ``` ## Workflow Examples ### Porting a Package to Dune ```bash # Setup unpac init myworkspace && cd myworkspace unpac opam repo add opam-repository /workspace/opam/opam-repository unpac project new myapp # Vendor and patch unpac opam add cmdliner unpac opam edit cmdliner cd opam/patches/cmdliner # Add dune files, remove _tags, etc. git add -A git commit -m "Port cmdliner to dune" cd ../../.. unpac opam done cmdliner # Use in project unpac opam merge cmdliner myapp cd project/myapp dune build ``` ### Updating a Patched Package ```bash # Update from upstream unpac opam update cmdliner # Rebase your patches unpac opam rebase cmdliner # If conflicts, resolve them: cd opam/patches/cmdliner # ... resolve conflicts ... git add -A git rebase --continue cd ../../.. unpac opam done cmdliner # Re-merge into project unpac opam merge cmdliner myapp ``` ### Adding Multiple Dependencies ```bash unpac opam add fmt unpac opam add logs unpac opam add cmdliner # Merge all into project unpac opam merge fmt myapp unpac opam merge logs myapp unpac opam merge cmdliner myapp ``` ## Directory Structure After setup, your workspace looks like: ``` myworkspace/ ├── git/ # Bare git repo (shared objects) ├── main/ # Metadata worktree │ └── unpac.toml # Configuration ├── project/ │ └── myapp/ # Project worktree │ ├── dune-project │ ├── dune │ └── vendor/ │ └── opam/ │ ├── cmdliner/ # Merged vendor code │ └── fmt/ └── opam/ # Package worktrees (on-demand) └── patches/ └── cmdliner/ # When editing ``` ## Configuration (unpac.toml) ```toml [opam] repositories = [ { name = "opam-repository", path = "/workspace/opam/opam-repository" } ] # compiler = "5.4.0" # Optional: pin compiler version [projects] myapp = {} ```