MCPcopy Index your code
hub / github.com/larksuite/cli / commitBinding

Function commitBinding

cmd/config/bind.go:407–471  ·  view source on GitHub ↗

commitBinding finalizes the bind: atomic write of the new workspace config, best-effort cleanup of stale keychain entries from the previous binding (if any), and a JSON success envelope. Cleanup runs only after the new config is durably written — if anything fails earlier, the old workspace stays us

(opts *BindOptions, appConfig *core.AppConfig, previousConfigBytes []byte, source, configPath string)

Source from the content-addressed store, hash-verified

405// is durably written — if anything fails earlier, the old workspace stays
406// usable.
407func commitBinding(opts *BindOptions, appConfig *core.AppConfig, previousConfigBytes []byte, source, configPath string) error {
408 multi := &core.MultiAppConfig{Apps: []core.AppConfig{*appConfig}}
409
410 if err := vfs.MkdirAll(core.GetConfigDir(), 0700); err != nil {
411 return errs.NewInternalError(errs.SubtypeFileIO, "failed to create workspace directory: %v", err).WithCause(err)
412 }
413 data, err := json.MarshalIndent(multi, "", " ")
414 if err != nil {
415 return errs.NewInternalError(errs.SubtypeStorage, "failed to marshal config: %v", err).WithCause(err)
416 }
417 if err := validate.AtomicWrite(configPath, append(data, '\n'), 0600); err != nil {
418 return errs.NewInternalError(errs.SubtypeStorage, "failed to write config %s: %v", configPath, err).WithCause(err)
419 }
420
421 replaced := previousConfigBytes != nil
422 // uiMsg renders human-facing TUI text (stderr success banner). Follows
423 // opts.UILang — zh by default; picker can flip it to en. --lang does
424 // not influence the TUI language.
425 uiMsg := getBindMsg(opts.UILang)
426 display := sourceDisplayName(source)
427
428 if replaced {
429 cleanupKeychainFromData(opts.Factory.Keychain, previousConfigBytes, appConfig)
430 }
431
432 fmt.Fprintln(opts.Factory.IOStreams.ErrOut,
433 fmt.Sprintf(uiMsg.BindSuccessHeader, display)+"\n"+uiMsg.BindSuccessNotice)
434
435 if opts.langExplicit && opts.Lang != "" {
436 fmt.Fprintln(opts.Factory.IOStreams.ErrOut, fmt.Sprintf(uiMsg.LangPreferenceSet, opts.Lang))
437 }
438
439 // TUI mode is a human sitting at a terminal; the BindSuccess notice on
440 // stderr is enough and a machine-readable JSON dump on stdout is just
441 // noise. Flag mode (Agent orchestration, scripts, piped output) still
442 // gets the full envelope for programmatic consumption.
443 if opts.IsTUI {
444 return nil
445 }
446
447 envelope := map[string]interface{}{
448 "ok": true,
449 "workspace": source,
450 "app_id": appConfig.AppId,
451 "config_path": configPath,
452 "replaced": replaced,
453 "identity": opts.Identity,
454 }
455 // JSON "message" follows the effective preference on disk (appConfig.Lang),
456 // not the raw --lang value: when --lang is omitted on re-bind, preferredLang
457 // has already inherited the prior preference into appConfig.Lang, and the
458 // message should respect that inherited choice. stderr above follows UILang.
459 prefMsg := getBindMsg(appConfig.Lang)
460 brand := brandDisplay(string(appConfig.Brand), appConfig.Lang)
461 switch opts.Identity {
462 case "bot-only":
463 envelope["message"] = fmt.Sprintf(prefMsg.MessageBotOnly, appConfig.AppId, display, brand)
464 case "user-default":

Callers 1

configBindRunFunction · 0.85

Calls 9

MkdirAllFunction · 0.92
GetConfigDirFunction · 0.92
NewInternalErrorFunction · 0.92
AtomicWriteFunction · 0.92
getBindMsgFunction · 0.85
sourceDisplayNameFunction · 0.85
cleanupKeychainFromDataFunction · 0.85
brandDisplayFunction · 0.85
WithCauseMethod · 0.45

Tested by

no test coverage detected