prepareFileEdit validates, reads, and computes edits for a single file without writing anything to disk.
(path string, edits []workspacesdk.FileEdit)
| 497 | // prepareFileEdit validates, reads, and computes edits for a single |
| 498 | // file without writing anything to disk. |
| 499 | func (api *API) prepareFileEdit(path string, edits []workspacesdk.FileEdit) (int, *pendingEdit, error) { |
| 500 | if path == "" { |
| 501 | return http.StatusBadRequest, nil, xerrors.New("\"path\" is required") |
| 502 | } |
| 503 | |
| 504 | if !filepath.IsAbs(path) { |
| 505 | return http.StatusBadRequest, nil, xerrors.Errorf("file path must be absolute: %q", path) |
| 506 | } |
| 507 | |
| 508 | if len(edits) == 0 { |
| 509 | return http.StatusBadRequest, nil, xerrors.New("must specify at least one edit") |
| 510 | } |
| 511 | |
| 512 | resolved, err := api.resolvePath(path) |
| 513 | if err != nil { |
| 514 | return http.StatusInternalServerError, nil, xerrors.Errorf("resolve symlink %q: %w", path, err) |
| 515 | } |
| 516 | origPath := path |
| 517 | path = resolved |
| 518 | |
| 519 | f, err := api.filesystem.Open(path) |
| 520 | if err != nil { |
| 521 | status := http.StatusInternalServerError |
| 522 | switch { |
| 523 | case errors.Is(err, os.ErrNotExist): |
| 524 | status = http.StatusNotFound |
| 525 | case errors.Is(err, os.ErrPermission): |
| 526 | status = http.StatusForbidden |
| 527 | } |
| 528 | return status, nil, err |
| 529 | } |
| 530 | defer f.Close() |
| 531 | |
| 532 | stat, err := f.Stat() |
| 533 | if err != nil { |
| 534 | return http.StatusInternalServerError, nil, err |
| 535 | } |
| 536 | |
| 537 | if stat.IsDir() { |
| 538 | return http.StatusBadRequest, nil, xerrors.Errorf("open %s: not a file", path) |
| 539 | } |
| 540 | |
| 541 | data, err := io.ReadAll(f) |
| 542 | if err != nil { |
| 543 | return http.StatusInternalServerError, nil, xerrors.Errorf("read %s: %w", path, err) |
| 544 | } |
| 545 | content := string(data) |
| 546 | oldContent := content |
| 547 | |
| 548 | for _, edit := range edits { |
| 549 | var err error |
| 550 | content, err = fuzzyReplace(content, edit) |
| 551 | if err != nil { |
| 552 | return http.StatusBadRequest, nil, xerrors.Errorf("edit %s: %w", path, err) |
| 553 | } |
| 554 | } |
| 555 | |
| 556 | return 0, &pendingEdit{ |
no test coverage detected