MCPcopy Index your code
hub / github.com/coder/coder / HandleEditFiles

Method HandleEditFiles

agent/agentfiles/files.go:375–495  ·  view source on GitHub ↗
(rw http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

373}
374
375func (api *API) HandleEditFiles(rw http.ResponseWriter, r *http.Request) {
376 ctx := r.Context()
377
378 var req workspacesdk.FileEditRequest
379 if !httpapi.Read(ctx, rw, r, &req) {
380 return
381 }
382
383 if len(req.Files) == 0 {
384 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
385 Message: "must specify at least one file",
386 })
387 return
388 }
389
390 // Duplicate entries both read the same file and race to write;
391 // the first entry's edits are silently lost. Resolve symlinks
392 // before comparing so two paths that alias the same real file
393 // (e.g. one via a symlink, one direct) don't slip past as
394 // distinct keys. prepareFileEdit resolves the path again for
395 // its own use; the double lstat cost is cheap compared to the
396 // data-loss risk of silent aliasing.
397 type seenEntry struct {
398 caller string
399 }
400 seenPaths := make(map[string]seenEntry, len(req.Files))
401 for _, f := range req.Files {
402 // On resolve error, use the raw path; phase 1 surfaces
403 // the error with its proper status code.
404 key := f.Path
405 if resolved, err := api.resolvePath(f.Path); err == nil {
406 key = resolved
407 }
408 if prev, dup := seenPaths[key]; dup {
409 msg := fmt.Sprintf("duplicate file path %q: combine edits into a single entry's \"edits\" list", f.Path)
410 if prev.caller != f.Path {
411 msg = fmt.Sprintf("duplicate file path %q aliases %q (same real file): combine edits into a single entry's \"edits\" list", f.Path, prev.caller)
412 }
413 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
414 Message: msg,
415 })
416 return
417 }
418 seenPaths[key] = seenEntry{caller: f.Path}
419 }
420
421 // Phase 1: compute all edits in memory. If any file fails
422 // (bad path, search miss, permission error), bail before
423 // writing anything.
424 var pending []pendingEdit
425 var combinedErr error
426 status := http.StatusOK
427 for _, edit := range req.Files {
428 s, p, err := api.prepareFileEdit(edit.Path, edit.Edits)
429 if s > status {
430 status = s
431 }
432 if err != nil {

Callers

nothing calls this directly

Calls 9

resolvePathMethod · 0.95
prepareFileEditMethod · 0.95
atomicWriteMethod · 0.95
ReadFunction · 0.92
WriteFunction · 0.92
FromContextFunction · 0.92
AddPathsMethod · 0.80
ContextMethod · 0.65
ErrorMethod · 0.45

Tested by

no test coverage detected