patch-fixer 0.3.2__py3-none-any.whl → 0.3.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- patch_fixer/cli.py +129 -0
- patch_fixer-0.3.3.dist-info/METADATA +123 -0
- patch_fixer-0.3.3.dist-info/RECORD +10 -0
- patch_fixer-0.3.3.dist-info/entry_points.txt +2 -0
- patch_fixer-0.3.2.dist-info/METADATA +0 -79
- patch_fixer-0.3.2.dist-info/RECORD +0 -8
- {patch_fixer-0.3.2.dist-info → patch_fixer-0.3.3.dist-info}/WHEEL +0 -0
- {patch_fixer-0.3.2.dist-info → patch_fixer-0.3.3.dist-info}/licenses/LICENSE +0 -0
- {patch_fixer-0.3.2.dist-info → patch_fixer-0.3.3.dist-info}/top_level.txt +0 -0
patch_fixer/cli.py
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""Command-line interface for patch-fixer."""
|
3
|
+
|
4
|
+
import argparse
|
5
|
+
import sys
|
6
|
+
from pathlib import Path
|
7
|
+
|
8
|
+
from .patch_fixer import fix_patch
|
9
|
+
from .split import split_patch
|
10
|
+
|
11
|
+
|
12
|
+
def fix_command(args):
|
13
|
+
"""Handle the fix command."""
|
14
|
+
with open(args.broken_patch, encoding='utf-8') as f:
|
15
|
+
patch_lines = f.readlines()
|
16
|
+
|
17
|
+
fixed_lines = fix_patch(patch_lines, args.original)
|
18
|
+
|
19
|
+
with open(args.output, 'w', encoding='utf-8') as f:
|
20
|
+
f.writelines(fixed_lines)
|
21
|
+
|
22
|
+
print(f"Fixed patch written to {args.output}")
|
23
|
+
return 0
|
24
|
+
|
25
|
+
|
26
|
+
def split_command(args):
|
27
|
+
"""Handle the split command."""
|
28
|
+
with open(args.patch_file, encoding='utf-8') as f:
|
29
|
+
patch_lines = f.readlines()
|
30
|
+
|
31
|
+
# read files to include from file or command line
|
32
|
+
if args.include_file:
|
33
|
+
with open(args.include_file, encoding='utf-8') as f:
|
34
|
+
files_to_include = [line.strip() for line in f if line.strip()]
|
35
|
+
else:
|
36
|
+
files_to_include = args.files or []
|
37
|
+
|
38
|
+
included, excluded = split_patch(patch_lines, files_to_include)
|
39
|
+
|
40
|
+
# write output files
|
41
|
+
with open(args.included_output, 'w', encoding='utf-8') as f:
|
42
|
+
f.writelines(included)
|
43
|
+
|
44
|
+
with open(args.excluded_output, 'w', encoding='utf-8') as f:
|
45
|
+
f.writelines(excluded)
|
46
|
+
|
47
|
+
print(f"Patch split into:")
|
48
|
+
print(f" Included: {args.included_output} ({len(included)} lines)")
|
49
|
+
print(f" Excluded: {args.excluded_output} ({len(excluded)} lines)")
|
50
|
+
|
51
|
+
return 0
|
52
|
+
|
53
|
+
|
54
|
+
def main():
|
55
|
+
"""Main entry point for the CLI."""
|
56
|
+
parser = argparse.ArgumentParser(
|
57
|
+
prog='patch-fixer',
|
58
|
+
description='Fix broken git patches or split them by file lists.'
|
59
|
+
)
|
60
|
+
|
61
|
+
subparsers = parser.add_subparsers(dest='command', help='Available commands')
|
62
|
+
|
63
|
+
# fix command
|
64
|
+
fix_parser = subparsers.add_parser(
|
65
|
+
'fix',
|
66
|
+
help='Fix a broken patch file'
|
67
|
+
)
|
68
|
+
fix_parser.add_argument(
|
69
|
+
'original',
|
70
|
+
help='Original file or directory that the patch applies to'
|
71
|
+
)
|
72
|
+
fix_parser.add_argument(
|
73
|
+
'broken_patch',
|
74
|
+
help='Path to the broken patch file'
|
75
|
+
)
|
76
|
+
fix_parser.add_argument(
|
77
|
+
'output',
|
78
|
+
help='Path where the fixed patch will be written'
|
79
|
+
)
|
80
|
+
|
81
|
+
# split command
|
82
|
+
split_parser = subparsers.add_parser(
|
83
|
+
'split',
|
84
|
+
help='Split a patch file based on file lists'
|
85
|
+
)
|
86
|
+
split_parser.add_argument(
|
87
|
+
'patch_file',
|
88
|
+
help='Path to the patch file to split'
|
89
|
+
)
|
90
|
+
split_parser.add_argument(
|
91
|
+
'included_output',
|
92
|
+
help='Output file for included files'
|
93
|
+
)
|
94
|
+
split_parser.add_argument(
|
95
|
+
'excluded_output',
|
96
|
+
help='Output file for excluded files'
|
97
|
+
)
|
98
|
+
split_parser.add_argument(
|
99
|
+
'-f', '--files',
|
100
|
+
nargs='*',
|
101
|
+
help='Files to include (can specify multiple)'
|
102
|
+
)
|
103
|
+
split_parser.add_argument(
|
104
|
+
'-i', '--include-file',
|
105
|
+
help='File containing list of files to include (one per line)'
|
106
|
+
)
|
107
|
+
|
108
|
+
# parse arguments
|
109
|
+
args = parser.parse_args()
|
110
|
+
|
111
|
+
if not args.command:
|
112
|
+
parser.print_help()
|
113
|
+
return 1
|
114
|
+
|
115
|
+
# dispatch to appropriate command
|
116
|
+
try:
|
117
|
+
if args.command == 'fix':
|
118
|
+
return fix_command(args)
|
119
|
+
elif args.command == 'split':
|
120
|
+
return split_command(args)
|
121
|
+
except Exception as e:
|
122
|
+
print(f"Error: {e}", file=sys.stderr)
|
123
|
+
return 1
|
124
|
+
|
125
|
+
return 0
|
126
|
+
|
127
|
+
|
128
|
+
if __name__ == "__main__":
|
129
|
+
sys.exit(main())
|
@@ -0,0 +1,123 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: patch-fixer
|
3
|
+
Version: 0.3.3
|
4
|
+
Summary: Fixes erroneous git apply patches to the best of its ability.
|
5
|
+
Maintainer-email: Alex Mueller <amueller474@gmail.com>
|
6
|
+
License-Expression: Apache-2.0
|
7
|
+
Project-URL: Homepage, https://github.com/ajcm474/patch-fixer
|
8
|
+
Project-URL: Issues, https://github.com/ajcm474/patch-fixer/issues
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
10
|
+
Classifier: Intended Audience :: Developers
|
11
|
+
Classifier: Programming Language :: Python
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
19
|
+
Classifier: Topic :: Software Development
|
20
|
+
Requires-Python: >=3.10
|
21
|
+
Description-Content-Type: text/markdown
|
22
|
+
License-File: LICENSE
|
23
|
+
Requires-Dist: GitPython
|
24
|
+
Provides-Extra: test
|
25
|
+
Requires-Dist: hypothesis; extra == "test"
|
26
|
+
Requires-Dist: pytest; extra == "test"
|
27
|
+
Requires-Dist: requests; extra == "test"
|
28
|
+
Dynamic: license-file
|
29
|
+
|
30
|
+
# patch-fixer
|
31
|
+
So you asked an LLM to generate a code diff, tried to apply it with `git apply`, and got a bunch of malformed patch errors? Well fear no more, `patch-fixer` is here to save the day... more or less.
|
32
|
+
|
33
|
+
This tool can also split patches into separate files based on file lists, making it easy to selectively apply changes.
|
34
|
+
|
35
|
+
## Installation
|
36
|
+
```bash
|
37
|
+
# Make sure you're using at least python 3.10
|
38
|
+
python -m venv .venv/
|
39
|
+
source .venv/bin/activate
|
40
|
+
pip install patch-fixer
|
41
|
+
```
|
42
|
+
|
43
|
+
## Usage
|
44
|
+
|
45
|
+
### Command Line Interface
|
46
|
+
|
47
|
+
After installation, `patch-fixer` provides a unified command-line interface:
|
48
|
+
|
49
|
+
#### Fixing broken patches:
|
50
|
+
```bash
|
51
|
+
patch-fixer fix original broken.patch fixed.patch
|
52
|
+
```
|
53
|
+
where:
|
54
|
+
- `original` is the file or directory you were trying to patch
|
55
|
+
- `broken.patch` is the malformed patch generated by the LLM
|
56
|
+
- `fixed.patch` is the output file containing the (hopefully) fixed patch
|
57
|
+
|
58
|
+
#### Splitting patches by file:
|
59
|
+
```bash
|
60
|
+
# Split with files specified on command line
|
61
|
+
patch-fixer split input.patch included.patch excluded.patch -f file1.py file2.py
|
62
|
+
|
63
|
+
# Split using a file list
|
64
|
+
patch-fixer split input.patch included.patch excluded.patch -i files_to_include.txt
|
65
|
+
```
|
66
|
+
where:
|
67
|
+
- `input.patch` is the patch file to split
|
68
|
+
- `included.patch` will contain changes for the specified files
|
69
|
+
- `excluded.patch` will contain changes for all other files
|
70
|
+
- `-f` allows specifying files directly on the command line
|
71
|
+
- `-i` reads the file list from a text file (one file per line)
|
72
|
+
|
73
|
+
### Python API
|
74
|
+
|
75
|
+
#### Fixing patches:
|
76
|
+
```python
|
77
|
+
from patch_fixer import fix_patch
|
78
|
+
|
79
|
+
patch_file = "/path/to/broken.patch"
|
80
|
+
original = "/path/to/original/state" # file or directory being patched
|
81
|
+
with open(patch_file, encoding="utf-8") as f:
|
82
|
+
patch_lines = f.readlines()
|
83
|
+
|
84
|
+
fixed_lines = fix_patch(patch_lines, original)
|
85
|
+
output_file = "/path/to/fixed.patch"
|
86
|
+
|
87
|
+
with open(output_file, 'w', encoding='utf-8') as f:
|
88
|
+
f.writelines(fixed_lines)
|
89
|
+
```
|
90
|
+
|
91
|
+
#### Splitting patches:
|
92
|
+
```python
|
93
|
+
from patch_fixer import split_patch
|
94
|
+
|
95
|
+
with open("input.patch", encoding="utf-8") as f:
|
96
|
+
patch_lines = f.readlines()
|
97
|
+
|
98
|
+
# split to include only specific files
|
99
|
+
files_to_include = ["./src/main.py", "./src/utils.py"]
|
100
|
+
included, excluded = split_patch(patch_lines, files_to_include)
|
101
|
+
|
102
|
+
# write the split patches
|
103
|
+
with open("included.patch", 'w', encoding='utf-8') as f:
|
104
|
+
f.writelines(included)
|
105
|
+
|
106
|
+
with open("excluded.patch", 'w', encoding='utf-8') as f:
|
107
|
+
f.writelines(excluded)
|
108
|
+
```
|
109
|
+
|
110
|
+
## Local Testing
|
111
|
+
```bash
|
112
|
+
git clone https://github.com/ajcm474/patch-fixer.git
|
113
|
+
cd patch-fixer
|
114
|
+
pip install -e .[test]
|
115
|
+
pytest
|
116
|
+
```
|
117
|
+
From version `0.3.0` onward (at least until version `1.0`), some test failures are expected
|
118
|
+
in bugfix versions as I like to use test-driven development to build out new features.
|
119
|
+
Please only report test failures if the same test existed and passed in the most recent `0.x.0` version.
|
120
|
+
|
121
|
+
## License
|
122
|
+
|
123
|
+
This is free and open source software, released under the Apache 2.0 License. See `LICENSE` for details.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
patch_fixer/__init__.py,sha256=n5DDMr4jbO3epK3ybBvjDyRddTWlWamN6ao5BC7xHFo,65
|
2
|
+
patch_fixer/cli.py,sha256=hgneS8DSCWBxv1l0u37n60FPGskAsDgodX9YxKgF-H0,3417
|
3
|
+
patch_fixer/patch_fixer.py,sha256=GAavb15H5cEoNFgGlO5hIY7EOF88VCsjHcLrfyGW4_0,20587
|
4
|
+
patch_fixer/split.py,sha256=l0rHM6-ZBuB9Iv6Ng6rxqZH5eKfvk2t87j__nDu67kM,3869
|
5
|
+
patch_fixer-0.3.3.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
6
|
+
patch_fixer-0.3.3.dist-info/METADATA,sha256=URfv2ws8naMvx3t8xsqN5JyGBlC38EydFYPwgivTnvQ,4117
|
7
|
+
patch_fixer-0.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
+
patch_fixer-0.3.3.dist-info/entry_points.txt,sha256=ftc6dP6B1zJouSPeCCJLZtx-EEGVSrNEwy4YhtnEoxA,53
|
9
|
+
patch_fixer-0.3.3.dist-info/top_level.txt,sha256=yyp3KjFgExJsrFsS9ZBCnkhb05xg8hPYhB7ncdpTOv0,12
|
10
|
+
patch_fixer-0.3.3.dist-info/RECORD,,
|
@@ -1,79 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: patch-fixer
|
3
|
-
Version: 0.3.2
|
4
|
-
Summary: Fixes erroneous git apply patches to the best of its ability.
|
5
|
-
Maintainer-email: Alex Mueller <amueller474@gmail.com>
|
6
|
-
License-Expression: Apache-2.0
|
7
|
-
Project-URL: Homepage, https://github.com/ajcm474/patch-fixer
|
8
|
-
Project-URL: Issues, https://github.com/ajcm474/patch-fixer/issues
|
9
|
-
Classifier: Development Status :: 3 - Alpha
|
10
|
-
Classifier: Intended Audience :: Developers
|
11
|
-
Classifier: Programming Language :: Python
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
13
|
-
Classifier: Programming Language :: Python :: 3.10
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
15
|
-
Classifier: Programming Language :: Python :: 3.12
|
16
|
-
Classifier: Programming Language :: Python :: 3.13
|
17
|
-
Classifier: Programming Language :: Python :: 3.14
|
18
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
19
|
-
Classifier: Topic :: Software Development
|
20
|
-
Requires-Python: >=3.10
|
21
|
-
Description-Content-Type: text/markdown
|
22
|
-
License-File: LICENSE
|
23
|
-
Requires-Dist: GitPython
|
24
|
-
Provides-Extra: test
|
25
|
-
Requires-Dist: hypothesis; extra == "test"
|
26
|
-
Requires-Dist: pytest; extra == "test"
|
27
|
-
Requires-Dist: requests; extra == "test"
|
28
|
-
Dynamic: license-file
|
29
|
-
|
30
|
-
# patch-fixer
|
31
|
-
So you asked an LLM to generate a code diff, tried to apply it with `git apply`, and got a bunch of malformed patch errors? Well fear no more, `patch_fixer.py` is here to save the day... more or less.
|
32
|
-
|
33
|
-
## Installation
|
34
|
-
```bash
|
35
|
-
# Make sure you're using at least python 3.10
|
36
|
-
python -m venv .venv/
|
37
|
-
source .venv/bin/activate
|
38
|
-
pip install patch-fixer
|
39
|
-
```
|
40
|
-
|
41
|
-
## Usage
|
42
|
-
### API:
|
43
|
-
```python
|
44
|
-
>>> from patch_fixer import fix_patch
|
45
|
-
>>>
|
46
|
-
>>> patch_file = "/path/to/broken.patch"
|
47
|
-
>>> original = "/path/to/original/state" # file or directory being patched
|
48
|
-
>>> with open(patch_file, encoding="utf-8") as f:
|
49
|
-
... patch_lines = f.readlines()
|
50
|
-
...
|
51
|
-
>>> fixed_lines = fix_patch(patch_lines, original)
|
52
|
-
>>> output_file = "/path/to/fixed.patch"
|
53
|
-
>>>
|
54
|
-
>>> with open(output_file, 'w', encoding='utf-8') as f:
|
55
|
-
... f.writelines(fixed_lines)
|
56
|
-
>>>
|
57
|
-
```
|
58
|
-
### Command line:
|
59
|
-
```bash
|
60
|
-
python patch_fixer/patch_fixer.py original broken.patch fixed.patch
|
61
|
-
```
|
62
|
-
where `original` is the file or directory you were trying to patch,
|
63
|
-
`broken.patch` is the malformed patch generated by the LLM,
|
64
|
-
and `fixed.patch` is the output file containing the (hopefully) fixed patch.
|
65
|
-
|
66
|
-
## Local Testing
|
67
|
-
```bash
|
68
|
-
git clone https://github.com/ajcm474/patch-fixer.git
|
69
|
-
cd patch-fixer
|
70
|
-
pip install -e .[test]
|
71
|
-
pytest
|
72
|
-
```
|
73
|
-
From version `0.3.0` onward (at least until version `1.0`), some test failures are expected
|
74
|
-
in bugfix versions as I like to use test-driven development to build out new features.
|
75
|
-
Please only report test failures if the same test existed and passed in the most recent `0.x.0` version.
|
76
|
-
|
77
|
-
## License
|
78
|
-
|
79
|
-
This is free and open source software, released under the Apache 2.0 License. See `LICENSE` for details.
|
@@ -1,8 +0,0 @@
|
|
1
|
-
patch_fixer/__init__.py,sha256=n5DDMr4jbO3epK3ybBvjDyRddTWlWamN6ao5BC7xHFo,65
|
2
|
-
patch_fixer/patch_fixer.py,sha256=GAavb15H5cEoNFgGlO5hIY7EOF88VCsjHcLrfyGW4_0,20587
|
3
|
-
patch_fixer/split.py,sha256=l0rHM6-ZBuB9Iv6Ng6rxqZH5eKfvk2t87j__nDu67kM,3869
|
4
|
-
patch_fixer-0.3.2.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
5
|
-
patch_fixer-0.3.2.dist-info/METADATA,sha256=DWi_Bf1beGb5Q0RyGxyDRlmb9RYjCuUhYcvJF0TisY0,2828
|
6
|
-
patch_fixer-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
-
patch_fixer-0.3.2.dist-info/top_level.txt,sha256=yyp3KjFgExJsrFsS9ZBCnkhb05xg8hPYhB7ncdpTOv0,12
|
8
|
-
patch_fixer-0.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|