# Vendorizing External Code

Bender's `vendor` command allows you to manage external dependencies that aren't natively packaged for Bender. It works by copying a subset of files from an upstream Git repository into a local directory within your project, allowing you to track changes and maintain local patches.

This flow is heavily inspired by the [`vendor.py`](https://github.com/lowRISC/opentitan/blob/master/util/vendor.py) script used in the [OpenTitan](https://opentitan.org/) project.

## Configuration

Vendorized packages are defined in the `vendor_package` section of your [`Bender.yml`](../manifest.md):

```yaml
vendor_package:
  - name: my_ip
    target_dir: "deps/my_ip"
    upstream: { git: "https://github.com/external/my_ip.git", rev: "abcd123" }
    include_from_upstream:
      - "src/*.sv"
      - "include/*.svh"
    exclude_from_upstream:
      - "src/deprecated/*"
    patch_dir: "deps/patches/my_ip"
    mapping:
      - {from: 'src/old_name.sv', to: 'src/new_name.sv' }
```

### Key Fields
- **`name`**: A unique identifier for the vendorized package.
- **`target_dir`**: Where the files should be copied to in your repository.
- **`upstream`**: The Git repository and specific revision (commit/tag/branch) to pull from.
- **`include_from_upstream`**: (Optional) Glob patterns of files to copy.
- **`exclude_from_upstream`**: (Optional) Glob patterns of files to ignore.
- **`patch_dir`**: (Optional) A directory containing `.patch` files to apply after copying.
- **`mapping`**: (Optional) A list of specific file renames or movements during the copy process.

## The Vendor Workflow

Using the configuration above, here is how you manage a vendorized IP:

### 1. Initialize (`init`)
To download the upstream code and copy it into your `target_dir`:

```sh
bender vendor init
```

Bender clones the upstream repository, filters the files based on your rules, and copies them to your project. If a `patch_dir` is specified, any existing patches are applied automatically.

> **Important:** Vendored files are not automatically picked up as compilation sources. After `bender vendor init`, you still need to list the relevant files (or globs matching them) in the [`sources`](../sources.md) section of your [`Bender.yml`](../manifest.md) for them to participate in script generation and source collection.

### 2. Make Local Changes and Diff
Assume you need to fix a bug in `deps/my_ip/src/top.sv`. You edit the file directly in your workspace. You can see how your local code differs from the upstream source (plus existing patches) by running:

```sh
bender vendor diff
```

### 3. Create a Patch (`patch`)
To make your fix permanent and shareable, stage the change and generate a patch:

```sh
# Stage the change in your main repository
git add deps/my_ip/src/top.sv

# Generate the patch file
bender vendor patch
```

Bender will prompt for a commit message and create a numbered patch file in your `patch_dir` (e.g., `0001-fix-bug.patch`).

### 4. Commit Everything
Now you can create an atomic commit in your repository that contains both the modified source and the new patch file:

```sh
git add deps/patches/my_ip/0001-fix-bug.patch
git commit -m "Update my_ip with local bugfix"
```

The next time you (or a teammate) run `bender vendor init`, Bender will pull the fresh upstream code and automatically apply your patch.

## Upstreaming Patches

If you want to contribute your fix back to the upstream repository:
1. Clone the upstream repository separately.
2. Check out the same revision (`abcd123`).
3. Apply your patch: `git am /path/to/your_repo/deps/patches/my_ip/0001-fix-bug.patch`.
4. The fix is now a proper Git commit in the upstream repo, with all metadata (author, timestamp) preserved.

## When to use Vendor?

Use the vendor flow when:
- The external IP does not have its own [`Bender.yml`](../manifest.md).
- You need to include only a small subset of a massive repository.
- You must maintain local modifications (bug fixes or tool workarounds) that haven't been merged upstream yet.
