Class: EasyAI::Command::Backup::Claude

Inherits:
Backup
  • Object
show all
Defined in:
lib/easyai/command/backup/claude.rb

Constant Summary collapse

EXCLUDED_KEYS =
%w[projects].freeze
KEYCHAIN_LABEL =
'Claude Code-credentials'.freeze
KEYCHAIN_BACKUP_KEY =
'_easyai_keychain'.freeze

Instance Method Summary collapse

Instance Method Details

#backup_dirObject



37
# File 'lib/easyai/command/backup/claude.rb', line 37

def backup_dir  = File.expand_path('~/.easyai/backup')

#backup_if_absentObject

供 easyai claude 运行前调用:仅当备份不存在且源文件存在时自动备份一次。 返回是否执行了备份;任何异常降级为 warning,绝不阻塞启动。



68
69
70
71
72
73
74
75
76
77
# File 'lib/easyai/command/backup/claude.rb', line 68

def backup_if_absent
  return false if File.exist?(backup_path)
  return false unless File.exist?(source_path)

  run
  true
rescue StandardError => e
  warn "  ⚠ 自动备份 Claude 登录信息失败(#{e.message}),继续启动"
  false
end

#backup_pathObject



38
# File 'lib/easyai/command/backup/claude.rb', line 38

def backup_path = File.join(backup_dir, '.claude.json')

#runObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/easyai/command/backup/claude.rb', line 45

def run
  source = read_json(source_path)
  EXCLUDED_KEYS.each { |key| source.delete(key) }

  keychain_value = read_keychain_credential(KEYCHAIN_LABEL)
  if keychain_value
    source[KEYCHAIN_BACKUP_KEY] = { KEYCHAIN_LABEL => keychain_value }
  end

  target = File.exist?(backup_path) ? read_json(backup_path) : {}
  before_keys = target.keys

  merged = deep_merge(target, source)

  FileUtils.mkdir_p(backup_dir)
  File.write(backup_path, JSON.pretty_generate(merged))
  File.chmod(0o600, backup_path) unless windows?

  report(before_keys, source.keys, merged.keys, keychain_value)
end

#source_pathObject

注意:路径用方法动态 expand_path,避免常量在加载期冻结真实 HOME, 让 spec 切换 ENV 后定位失败(同 LocalConfig.config_path 的处理)



36
# File 'lib/easyai/command/backup/claude.rb', line 36

def source_path = File.expand_path('~/.claude.json')

#validate!Object



40
41
42
43
# File 'lib/easyai/command/backup/claude.rb', line 40

def validate!
  super
  help! "源文件不存在: #{source_path}\n请先登录 Claude Code 后再备份。" unless File.exist?(source_path)
end