mpatch 0.3.0

A smart, context-aware patch tool that applies diffs using fuzzy matching, ideal for AI-generated code.
Documentation
# Mpatch


[![CI Status](https://img.shields.io/github/actions/workflow/status/romelium/mpatch/ci.yml?branch=main&style=flat-square&logo=githubactions&logoColor=white)](https://github.com/romelium/mpatch/actions/workflows/ci.yml)
[![Latest Release](https://img.shields.io/github/v/release/romelium/mpatch?style=flat-square&logo=github&logoColor=white)](https://github.com/romelium/mpatch/releases/latest)
[![Crates.io](https://img.shields.io/crates/v/mpatch?style=flat-square&logo=rust&logoColor=white)](https://crates.io/crates/mpatch)
[![License: MIT](https://img.shields.io/crates/l/mpatch)](https://opensource.org/licenses/MIT)
[![Rust Version](https://img.shields.io/badge/rust-1.83.0%2B-orange?style=flat-square&logo=rust)](https://www.rust-lang.org/)
[![Downloads](https://img.shields.io/crates/d/mpatch?style=flat-square)](https://crates.io/crates/mpatch)

**A smart, context-aware patch tool for the modern developer.**

`mpatch` applies unified diffs to your codebase, but with a twist. Instead of relying on strict line numbers, it finds the correct location to apply changes based on the *surrounding context*. It's designed to work seamlessly with patches generated by AI, copied from pull requests, or stored in markdown files.

---

## Why `mpatch`?


The primary motivation for `mpatch` comes from working with Large Language Models (LLMs).

When you ask an AI like ChatGPT, Claude, or Copilot to refactor code, it often provides the changes in a convenient markdown format with ` ```diff` or ` ```patch` blocks. **However, you can't trust that the line numbers are correct.** Sometimes, even the surrounding context lines aren't a perfect, character-for-character match to your current code. A standard `patch` command will often fail in these situations.

**This is the core problem `mpatch` was built to solve.**

It intelligently ignores line numbers and uses a fuzzy, context-based search to find where the patch *should* apply. This makes it highly resilient to the small inaccuracies common in AI-generated diffs, allowing you to apply them with confidence.

This same logic makes it perfect for other common developer scenarios where patches are less formal:
*   **Code Snippets:** Using a diff copied from a GitHub comment, a blog post, or a team chat.
*   **Iterative Development:** Applying a patch to a branch that has slightly diverged from where the patch was created.

---

## Core Features


*   **Markdown-Aware:** Directly parses unified diffs from within ````diff ` or ````patch ` code blocks in any text or markdown file.
*   **Context-Driven:** Ignores `@@ ... @@` line numbers, finding patch locations by matching context lines. This makes it resilient to minor preceding changes in a file.
*   **Fuzzy Matching:** If an exact context match isn't found, `mpatch` uses a sophisticated similarity algorithm to find the *best* fuzzy match. This logic can handle cases where lines have been added or removed near the patch location, allowing patches to apply even when the surrounding context has moderately diverged.
*   **Safe & Secure:** Includes a `--dry-run` mode to preview changes and built-in protection against path traversal attacks.
*   **Flexible:** Handles multiple files and multiple hunks in a single pass. It correctly processes file creations, modifications, and deletions (by removing all content from a file).
*   **Informative Logging:** Adjustable verbosity levels (`-v`, `-vv`) to see exactly what `mpatch` is doing.

---

## Installation


### Method 1: Using `cargo-binstall` (Recommended)


For users with the [Rust toolchain](https://rustup.rs/), `cargo-binstall` is the fastest way to install `mpatch`. It downloads pre-compiled binaries, avoiding a local build.

First, install `cargo-binstall` if you don't have it:
```bash
cargo install cargo-binstall
```

Then, install `mpatch`:
```bash
cargo binstall mpatch
```

### Method 2: From GitHub Releases (Manual)


For users who don't need to build from source, pre-compiled binaries are the simplest option.

1.  Navigate to the [**GitHub Releases page**]https://github.com/romelium/mpatch/releases.
2.  Download the appropriate archive for your system (e.g., `mpatch-x86_64-unknown-linux-gnu.tar.gz`).
3.  Extract the `mpatch` executable.
4.  Move the executable to a directory in your system's `PATH` (e.g., `/usr/local/bin` on Linux/macOS, or `~/.cargo/bin`).

### Method 3: From Crates.io (Build from Source)


If you have the [Rust toolchain](https://rustup.rs/) installed, you can compile and install `mpatch` from the official package registry:

```bash
cargo install mpatch
```

### Method 4: From Source (for Developers)


To build the very latest development version or to contribute to the project:

```bash
# Install directly from the main branch of the repository

cargo install --git https://github.com/romelium/mpatch.git

# Or, to work on the code locally:

git clone https://github.com/romelium/mpatch.git
cd mpatch
cargo install --path .
```

---

## Usage


### Basic Command


```bash
mpatch [OPTIONS] <INPUT_FILE> <TARGET_DIR>
```

### Verifying Changes with `--dry-run`


Before modifying any files, you can preview the exact changes using the `-n` or `--dry-run` flag. This is the safest way to start.

```bash
mpatch --dry-run changes.md my-project/
```

This will produce a diff of the proposed changes for each file, printed directly to your terminal:

```
----- Proposed Changes for src/main.rs -----
--- a
+++ b
@@ -1,5 +1,5 @@
 fn main() {
-    // This is the original program
-    println!("Hello, world!");
+    // This is the updated program
+    println!("Hello, mpatch!");
 }

------------------------------------
DRY RUN completed. No files were modified.
```

### Applying Changes


Once you are confident in the proposed changes, run the command without `--dry-run`. Use `-v` for informational output.

```bash
mpatch -v changes.md my-project/
```

You will see a confirmation log:
```
Found 1 patch operation(s) to perform.
Fuzzy matching enabled with threshold: 0.70

>>> Operation 1/1
Applying patch to: src/main.rs
  Applying Hunk 1/1...
  Successfully wrote changes to 'my-project/src/main.rs'

--- Summary ---
Successful operations: 1
Failed operations:     0
```

### Key Options


*   `-n`, `--dry-run`: Show what changes would be made without modifying any files.
*   `-f`, `--fuzz-factor <FACTOR>`: Set the similarity threshold for fuzzy matching, from `0.0` (disabled) to `1.0` (exact match). Default is `0.7`.
*   `-v`, `--verbose`: Increase logging output. Use `-v` for info, `-vv` for debug, `-vvv` for trace, and `-vvvv` to generate a comprehensive debug report file.

---

## Troubleshooting


If a patch doesn't apply as expected, the best first step is to increase the logging verbosity to understand what `mpatch` is doing.

*   **Run with `-v`:** This shows which files and hunks are being processed.
*   **Run with `-vv`:** This provides detailed debug information, including why a hunk might have failed to apply (e.g., "ambiguous match", "context not found").
*   **Run with `-vvv`:** This enables trace-level logging, showing the fuzzy matching scores and every step of the decision-making process.

### Generating a Debug Report


For complex issues, the easiest way to gather all necessary information for a bug report is to use the `-vvvv` flag.

```bash
mpatch -vvvv changes.md my-project/
```

This command will:
1.  Print full trace logs to your terminal.
2.  Create a file named `mpatch-debug-report-[timestamp].md` in your current directory.

This single markdown file contains everything needed to reproduce the issue: the command you ran, system information, the full input patch file, the original content of all target files, and the complete trace log.

---

## License


This project is licensed under [MIT LICENSE](LICENSE)

## Contributing


Contributions are welcome! Whether it's a bug report, a feature request, or a pull request, your input is valued.

### Reporting Issues


When opening an issue, the best way to help us is to provide a debug report.

1.  Run your command again with the `-vvvv` flag.
    ```bash
    mpatch -vvvv [YOUR_ARGS]

    ```
2.  This will create a `mpatch-debug-report-[timestamp].md` file.
3.  Create a new issue on GitHub.
4.  Drag and drop the generated `.md` file into the issue description to attach it.
5.  Add any additional comments about what you expected to happen versus what actually happened.

This self-contained report gives us all the context we need to investigate the problem efficiently.

### Pull Requests


1.  Fork the repository.
2.  Create a new branch for your feature or bug fix.
3.  Make your changes.
4.  Add tests for your changes in the `tests/` directory.
5.  Ensure all tests pass by running `cargo test`.
6.  Format your code with `cargo fmt`.
7.  Submit a pull request with a clear description of your changes.