|
27 | 27 | {:error true |
28 | 28 | :contents [{:type :text |
29 | 29 | :text (format "Access denied - path %s outside allowed directories: %s" |
30 | | - (h/file-path "/foo/qux") |
31 | | - (h/file-path "/foo/bar/baz"))}]} |
| 30 | + (h/file-path "/foo/qux") |
| 31 | + (h/file-path "/foo/bar/baz"))}]} |
32 | 32 | (with-redefs [fs/canonicalize (constantly (h/file-path "/foo/qux")) |
33 | 33 | fs/exists? (constantly true)] |
34 | 34 | ((get-in f.tools.filesystem/definitions ["eca_list_directory" :handler]) |
|
39 | 39 | {:error false |
40 | 40 | :contents [{:type :text |
41 | 41 | :text (format (str "[FILE] %s\n" |
42 | | - "[DIR] %s\n") |
43 | | - (h/file-path "/foo/bar/baz/some.clj") |
44 | | - (h/file-path "/foo/bar/baz/qux"))}]} |
| 42 | + "[DIR] %s\n") |
| 43 | + (h/file-path "/foo/bar/baz/some.clj") |
| 44 | + (h/file-path "/foo/bar/baz/qux"))}]} |
45 | 45 | (with-redefs [fs/exists? (constantly true) |
46 | 46 | fs/starts-with? (constantly true) |
47 | 47 | fs/list-dir (constantly [(fs/path (h/file-path "/foo/bar/baz/some.clj")) |
|
119 | 119 | {:error true |
120 | 120 | :contents [{:type :text |
121 | 121 | :text (format "Access denied - path %s outside allowed directories: %s" |
122 | | - (h/file-path "/foo/qux/new_file.clj") |
123 | | - (h/file-path "/foo/bar"))}]} |
| 122 | + (h/file-path "/foo/qux/new_file.clj") |
| 123 | + (h/file-path "/foo/bar"))}]} |
124 | 124 | (with-redefs [f.tools.filesystem/allowed-path? (constantly false)] |
125 | 125 | ((get-in f.tools.filesystem/definitions ["eca_write_file" :handler]) |
126 | 126 | {"path" (h/file-path "/foo/qux/new_file.clj")} |
|
153 | 153 | {:error false |
154 | 154 | :contents [{:type :text |
155 | 155 | :text (str (h/file-path "/project/foo/bar/baz.txt") "\n" |
156 | | - (h/file-path "/project/foo/qux.txt") "\n" |
157 | | - (h/file-path "/project/foo/qux.clj"))}]} |
| 156 | + (h/file-path "/project/foo/qux.txt") "\n" |
| 157 | + (h/file-path "/project/foo/qux.clj"))}]} |
158 | 158 | (with-redefs [fs/exists? (constantly true) |
159 | 159 | fs/glob (constantly [(fs/path (h/file-path "/project/foo/bar/baz.txt")) |
160 | 160 | (fs/path (h/file-path "/project/foo/qux.txt")) |
|
168 | 168 | {:error false |
169 | 169 | :contents [{:type :text |
170 | 170 | :text (str (h/file-path "/project/foo/bar/baz.txt") "\n" |
171 | | - (h/file-path "/project/foo/qux.txt"))}]} |
| 171 | + (h/file-path "/project/foo/qux.txt"))}]} |
172 | 172 | (with-redefs [fs/exists? (constantly true) |
173 | 173 | fs/glob (constantly [(fs/path (h/file-path "/project/foo/bar/baz.txt")) |
174 | 174 | (fs/path (h/file-path "/project/foo/qux.txt"))])] |
|
268 | 268 | (with-redefs [fs/exists? (constantly true) |
269 | 269 | fs/readable? (constantly false) |
270 | 270 | f.tools.filesystem/allowed-path? (constantly true)] |
271 | | - ((get-in f.tools.filesystem/definitions ["eca_replace_in_file" :handler]) |
| 271 | + ((get-in f.tools.filesystem/definitions ["eca_edit_file" :handler]) |
272 | 272 | {"path" (h/file-path "/foo/qux") |
273 | | - "original_content" "some-cool-text" |
274 | | - "new_content" "another-boring-text"} |
| 273 | + "start_line" 2 |
| 274 | + "end_line" 3 |
| 275 | + "content" "updated"} |
275 | 276 | {:db {:workspace-folders [{:uri (h/file-uri "file:///foo/bar/baz") :name "foo"}]}}))))) |
276 | | - (testing "original content not found" |
277 | | - (is (match? |
278 | | - {:error true |
279 | | - :contents [{:type :text |
280 | | - :text (format "Original content not found in %s" (h/file-path "/project/foo/my-file.txt"))}]} |
| 277 | + |
| 278 | + (testing "invalid line range (start_line > end_line)" |
| 279 | + (is (thrown? |
| 280 | + Exception |
281 | 281 | (with-redefs [fs/exists? (constantly true) |
282 | 282 | fs/readable? (constantly true) |
283 | 283 | f.tools.filesystem/allowed-path? (constantly true) |
284 | | - slurp (constantly "Hey, here is some-cool-text in this file!")] |
285 | | - ((get-in f.tools.filesystem/definitions ["eca_replace_in_file" :handler]) |
286 | | - {"path" (h/file-path "/project/foo/my-file.txt") |
287 | | - "original_content" "other-cool-text" |
288 | | - "new_content" "another-boring-text"} |
289 | | - {:db {:workspace-folders [{:uri (h/file-uri "file:///project/foo") :name "foo"}]}}))))) |
290 | | - (testing "original content found and replaced first" |
| 284 | + slurp (constantly "a\nb\nc")] ; just for completeness |
| 285 | + ((get-in f.tools.filesystem/definitions ["eca_edit_file" :handler]) |
| 286 | + {"path" (h/file-path "/foo/qux") |
| 287 | + "start_line" 3 |
| 288 | + "end_line" 2 |
| 289 | + "content" "no-op"} |
| 290 | + {:db {:workspace-folders [{:uri (h/file-uri "file:///foo/bar") :name "bar"}]}}))))) |
| 291 | + |
| 292 | + (testing "replace 2nd and 3rd lines in file" |
291 | 293 | (let [file-content* (atom {})] |
292 | 294 | (is (match? |
293 | 295 | {:error false |
294 | 296 | :contents [{:type :text |
295 | | - :text (format "Successfully replaced content in %s." (h/file-path "/project/foo/my-file.txt"))}]} |
| 297 | + :text (format "Successfully replaced lines 2-3 in %s." (h/file-path "/project/foo/my-file.txt"))}]} |
296 | 298 | (with-redefs [fs/exists? (constantly true) |
297 | 299 | fs/readable? (constantly true) |
298 | 300 | f.tools.filesystem/allowed-path? (constantly true) |
299 | | - slurp (constantly "Hey, here is some-cool-text in this file! here as well: some-cool-text") |
| 301 | + slurp (constantly "line1\nold2\nold3\nline4") |
300 | 302 | spit (fn [f content] (swap! file-content* assoc f content))] |
301 | | - ((get-in f.tools.filesystem/definitions ["eca_replace_in_file" :handler]) |
| 303 | + ((get-in f.tools.filesystem/definitions ["eca_edit_file" :handler]) |
302 | 304 | {"path" (h/file-path "/project/foo/my-file.txt") |
303 | | - "original_content" "some-cool-text" |
304 | | - "new_content" "another-boring-text"} |
| 305 | + "start_line" 2 |
| 306 | + "end_line" 3 |
| 307 | + "content" "new2\nnew3"} |
305 | 308 | {:db {:workspace-folders [{:uri (h/file-uri "file:///project/foo") :name "foo"}]}})))) |
306 | 309 | (is (match? |
307 | | - {(h/file-path "/project/foo/my-file.txt") "Hey, here is another-boring-text in this file! here as well: some-cool-text"} |
| 310 | + {(h/file-path "/project/foo/my-file.txt") "line1\nnew2\nnew3\nline4"} |
308 | 311 | @file-content*)))) |
309 | | - (testing "original content found and replaced all" |
| 312 | + |
| 313 | + (testing "replace first line only in file" |
| 314 | + (let [file-content* (atom {})] |
| 315 | + (is (match? |
| 316 | + {:error false |
| 317 | + :contents [{:type :text |
| 318 | + :text (format "Successfully replaced lines 1-1 in %s." (h/file-path "/project/foo/my-file.txt"))}]} |
| 319 | + (with-redefs [fs/exists? (constantly true) |
| 320 | + fs/readable? (constantly true) |
| 321 | + f.tools.filesystem/allowed-path? (constantly true) |
| 322 | + slurp (constantly "orig1\nkeep2\nkeep3") |
| 323 | + spit (fn [f content] (swap! file-content* assoc f content))] |
| 324 | + ((get-in f.tools.filesystem/definitions ["eca_edit_file" :handler]) |
| 325 | + {"path" (h/file-path "/project/foo/my-file.txt") |
| 326 | + "start_line" 1 |
| 327 | + "end_line" 1 |
| 328 | + "content" "updated1"} |
| 329 | + {:db {:workspace-folders [{:uri (h/file-uri "file:///project/foo") :name "foo"}]}})))) |
| 330 | + (is (match? |
| 331 | + {(h/file-path "/project/foo/my-file.txt") "updated1\nkeep2\nkeep3"} |
| 332 | + @file-content*)))) |
| 333 | + |
| 334 | + (testing "replace last line in file" |
310 | 335 | (let [file-content* (atom {})] |
311 | 336 | (is (match? |
312 | 337 | {:error false |
313 | 338 | :contents [{:type :text |
314 | | - :text (format "Successfully replaced content in %s." (h/file-path "/project/foo/my-file.txt"))}]} |
| 339 | + :text (format "Successfully replaced lines 4-4 in %s." (h/file-path "/project/foo/my-file.txt"))}]} |
315 | 340 | (with-redefs [fs/exists? (constantly true) |
316 | 341 | fs/readable? (constantly true) |
317 | 342 | f.tools.filesystem/allowed-path? (constantly true) |
318 | | - slurp (constantly "Hey, here is some-cool-text in this file! here as well: some-cool-text") |
| 343 | + slurp (constantly "keep1\nkeep2\nkeep3\nlast") |
319 | 344 | spit (fn [f content] (swap! file-content* assoc f content))] |
320 | | - ((get-in f.tools.filesystem/definitions ["eca_replace_in_file" :handler]) |
| 345 | + ((get-in f.tools.filesystem/definitions ["eca_edit_file" :handler]) |
321 | 346 | {"path" (h/file-path "/project/foo/my-file.txt") |
322 | | - "original_content" "some-cool-text" |
323 | | - "new_content" "another-boring-text" |
324 | | - "all_occurrences" true} |
| 347 | + "start_line" 4 |
| 348 | + "end_line" 4 |
| 349 | + "content" "newlast"} |
325 | 350 | {:db {:workspace-folders [{:uri (h/file-uri "file:///project/foo") :name "foo"}]}})))) |
326 | 351 | (is (match? |
327 | | - {(h/file-path "/project/foo/my-file.txt") "Hey, here is another-boring-text in this file! here as well: another-boring-text"} |
| 352 | + {(h/file-path "/project/foo/my-file.txt") "keep1\nkeep2\nkeep3\nnewlast"} |
328 | 353 | @file-content*))))) |
329 | 354 |
|
330 | 355 | (deftest move-file-test |
|
354 | 379 | {:error false |
355 | 380 | :contents [{:type :text |
356 | 381 | :text (format "Successfully moved %s to %s" |
357 | | - (h/file-path "/foo/bar/some_file.clj") |
358 | | - (h/file-path "/foo/bar/other_file.clj"))}]} |
| 382 | + (h/file-path "/foo/bar/some_file.clj") |
| 383 | + (h/file-path "/foo/bar/other_file.clj"))}]} |
359 | 384 | (with-redefs [fs/exists? (fn [path] (not (string/includes? path "other_file.clj"))) |
360 | 385 | f.tools.filesystem/allowed-path? (constantly true) |
361 | 386 | fs/move (constantly true)] |
|
0 commit comments