Skip to content

Commit a2ae722

Browse files
Implement a basic form of the diff/patch code block handling
This is a special case as it needs to know the original file's path instead of just returning something so it is handler in the `processBlock` function itself.
1 parent 6892849 commit a2ae722

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

demo/file-management/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
file-name-external.txt
22
file-name-internal.txt
3+
file-name.txt

demo/file-management/readme.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,40 @@ Hello, world! (Internal again)
5858

5959
The prefix to use here is `??`.
6060

61+
## Patch
62+
63+
When using the `diff` or `patch` language tags, special treatment will be used
64+
and the content of the code block will be applied to the file by Git:
65+
66+
```txt ..file-name.txt
67+
1
68+
2
69+
3
70+
4
71+
```
72+
73+
The file name is specified as the handler meta in this case!
74+
75+
```diff file-name.txt
76+
@@ -1,4 +1,4 @@
77+
-1
78+
+100
79+
2
80+
-3
81+
+300
82+
4
83+
```
84+
85+
We can check the operation worked with the match operation from before:
86+
87+
```txt ??file-name.txt
88+
100
89+
2
90+
300
91+
4
92+
93+
```
94+
6195
## Move, delete
6296

6397
Deleting and moving files is relegated to the shell handler, e.g.:

processBlocks.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { $ } from 'bun';
12
import type { Block } from './Block';
23
import fs from 'fs';
34
import processStdoutBlock from './processStdoutBlock';
@@ -36,7 +37,7 @@ export default async function processBlocks(blocks: Block[]) {
3637
throw new Error(`Duplicate handlers for the ${tag} language tag`);
3738
}
3839

39-
if (!handlerWithMeta && !handlerWithoutMeta) {
40+
if (!handlerWithMeta && !handlerWithoutMeta && block.tag !== 'diff' && block.tag !== 'patch') {
4041
continue;
4142
}
4243

@@ -51,6 +52,27 @@ export default async function processBlocks(blocks: Block[]) {
5152
continue;
5253
}
5354

55+
// Bypass the handlers if the block mode is `diff` or `patch` and apply it
56+
if (block.tag === 'diff' || block.tag === 'patch') {
57+
if (!(await Bun.file(block.meta).exists())) {
58+
console.error(`'${block.meta}' does not exist to patch changes to`);
59+
}
60+
61+
const { stdout: stdoutBuffer, stderr: stderrBuffer } = await $`echo ${block.code} | patch ${block.meta}`.quiet();
62+
const stdout = stdoutBuffer.toString();
63+
const stderr = stderrBuffer.toString();
64+
65+
if (stdout !== `patching file ${block.meta}\n`) {
66+
console.error(stdout);
67+
}
68+
69+
if (stderr) {
70+
console.error(stderr);
71+
}
72+
73+
continue;
74+
}
75+
5476
try {
5577
// See https://github.com/oven-sh/bun/issues/14874 for a better option
5678
const originalConsoleLog = console.log;

readme.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,20 @@ do in `processBlocks` and compare the expected output with the real output.
167167

168168
In file management demos, also check the files on disk and clean up after.
169169

170-
### Consider how to implement the `patch` and `diff` language tags
171-
172-
The `patch` and `diff` language tags might need special treatment as handlers do
173-
not have access to the file content so these will need to work on the file
174-
management level not like normal handlers probably.
175-
176-
See the `MarkRight` file in the Node-based implementation I replaced to see how
177-
it used to work, but for the Bun-based implementation, probably just call out to
178-
Git to apply the changes.
170+
### Find a way to allow `diff`/`patch` code blocks to not have hunk context line
171+
172+
The `@@` line.
173+
The `patch` utility seems to require these, it will not try to match and patch
174+
loosely.
175+
The `git apply` command has `--unidiff-zero` which seems to allow not providing
176+
the context lines but it was giving me trouble probably because the file I am
177+
trying to apply to is not necessarily tracked by Git?
178+
179+
If there is no way to get rid of these, maybe I could generate the hunk context
180+
by assuming the changes are for the whole file?
181+
This would massively lessen the utility of this code block though.
182+
Maybe there is a path where I derive the start and end lines and only require
183+
that the diff/patch code is a single hunk maybe?
179184

180185
### Consider allowing to specify what shell to use in the shell handler
181186

0 commit comments

Comments
 (0)