Class: Appship::Cache
- Inherits:
-
Object
- Object
- Appship::Cache
- Defined in:
- lib/appship/cache.rb
Constant Summary collapse
- DEFAULT_PATH =
File.("~/.appship/.config")
- DEFAULT_BUILD_DIR =
File.("~/.appship/build")
- LEGACY_PATH =
File.("~/.appship/.env")
Instance Attribute Summary collapse
-
#entries ⇒ Object
readonly
Returns the value of attribute entries.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
- .collect_interactively!(path, project_dir: Dir.pwd, provider: "pgyer") ⇒ Object
- .create_file!(path) ⇒ Object
- .credential_key_for(provider) ⇒ Object
- .infer_project_name!(project_dir) ⇒ Object
- .load(path = DEFAULT_PATH, project_dir: Dir.pwd, interactive: true, provider: "pgyer") ⇒ Object
- .missing_credentials_message(path, provider, created: false, empty: false) ⇒ Object
- .prompt_optional(name) ⇒ Object
- .prompt_required(name) ⇒ Object
Instance Method Summary collapse
-
#initialize(path = DEFAULT_PATH) ⇒ Cache
constructor
A new instance of Cache.
- #resolve(project_name: nil, project_dir: Dir.pwd, provider: "pgyer", interactive: true, credential_overrides: {}) ⇒ Object
- #update_profile!(entry, values) ⇒ Object
Constructor Details
#initialize(path = DEFAULT_PATH) ⇒ Cache
Returns a new instance of Cache.
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/appship/cache.rb', line 94 def initialize(path = DEFAULT_PATH) @path = File.(path) raise ConfigurationError, "本机缓存文件不存在: #{@path}\n请使用 --env-file 指定路径" unless File.file?(@path) @entries = parse(File.read(@path)) raise ConfigurationError, "缓存文件必须是字典数组: #{@path}" unless @entries.is_a?(Array) @entries = @entries.map { |entry| normalize(entry) } raise ConfigurationError, "缓存文件中没有有效项目: #{@path}" if @entries.empty? rescue Psych::SyntaxError => e raise ConfigurationError, "缓存文件解析失败: #{e.}" end |
Instance Attribute Details
#entries ⇒ Object (readonly)
Returns the value of attribute entries.
9 10 11 |
# File 'lib/appship/cache.rb', line 9 def entries @entries end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
9 10 11 |
# File 'lib/appship/cache.rb', line 9 def path @path end |
Class Method Details
.collect_interactively!(path, project_dir: Dir.pwd, provider: "pgyer") ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/appship/cache.rb', line 44 def self.collect_interactively!(path, project_dir: Dir.pwd, provider: "pgyer") project_name = infer_project_name!(project_dir) provider_name = provider.to_s == "fir" ? "fir.im" : "pgyer" credential_key = credential_key_for(provider) puts "" puts "首次使用 appship #{provider_name},请填写本机项目缓存。" puts "缓存文件: #{path}" puts "" puts "✅ 已从 #{File.basename(project_name)}.xcodeproj 识别 project_name: #{project_name}" app_name = prompt_required("app_name") data = { "project_name" => project_name, "app_name" => app_name, credential_key => prompt_required(credential_key) } password_key = provider.to_s == "fir" ? "fir_password" : "pgyer_password" data[password_key] = prompt_optional(password_key) File.write(path, JSON.pretty_generate([data]) + "\n") File.chmod(0o600, path) puts "" puts "✅ 本机缓存已保存: #{path}" new(path) end |
.create_file!(path) ⇒ Object
36 37 38 39 40 41 42 |
# File 'lib/appship/cache.rb', line 36 def self.create_file!(path) FileUtils.mkdir_p(File.dirname(path)) File.chmod(0o700, File.dirname(path)) if File.directory?(File.dirname(path)) File.write(path, "[]\n") unless File.exist?(path) File.chmod(0o600, path) path end |
.credential_key_for(provider) ⇒ Object
140 141 142 |
# File 'lib/appship/cache.rb', line 140 def self.credential_key_for(provider) provider.to_s == "fir" ? "fir_api_key" : "pgyer_api_key" end |
.infer_project_name!(project_dir) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/appship/cache.rb', line 68 def self.infer_project_name!(project_dir) xcodeprojects = Dir[File.join(File.(project_dir), "*.xcodeproj")] if xcodeprojects.empty? raise ConfigurationError, "当前目录找不到 .xcodeproj,无法自动设置 project_name: #{File.(project_dir)}" end if xcodeprojects.length > 1 names = xcodeprojects.map { |path| File.basename(path, ".xcodeproj") }.join(", ") raise ConfigurationError, "当前目录找到多个 .xcodeproj,无法确定 project_name: #{names}" end File.basename(xcodeprojects.first, ".xcodeproj") end |
.load(path = DEFAULT_PATH, project_dir: Dir.pwd, interactive: true, provider: "pgyer") ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/appship/cache.rb', line 11 def self.load(path = DEFAULT_PATH, project_dir: Dir.pwd, interactive: true, provider: "pgyer") = File.(path) # 兼容早期版本的 ~/.appship/.env;发现旧缓存时迁移到新的 .config。 if == DEFAULT_PATH && !File.file?() && File.file?(LEGACY_PATH) FileUtils.mkdir_p(File.dirname()) FileUtils.cp(LEGACY_PATH, ) File.chmod(0o600, ) end unless File.file?() create_file!() return collect_interactively!(, project_dir: project_dir, provider: provider) if interactive && $stdin.tty? raise ConfigurationError, (, provider, created: true) end if File.read().strip.empty? return collect_interactively!(, project_dir: project_dir, provider: provider) if interactive && $stdin.tty? raise ConfigurationError, (, provider, empty: true) end new() end |
.missing_credentials_message(path, provider, created: false, empty: false) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/appship/cache.rb', line 144 def self.(path, provider, created: false, empty: false) prefix = if created "已创建本机缓存文件: #{path}" elsif empty "本机缓存文件为空: #{path}" else "本机缓存文件无效: #{path}" end key = credential_key_for(provider) password_key = key == "pgyer_api_key" ? "pgyer_password" : "fir_password" suffix = ";#{password_key} 可为空" "#{prefix}\n请填写 project_name、app_name、#{key}#{suffix}" end |
.prompt_optional(name) ⇒ Object
89 90 91 92 |
# File 'lib/appship/cache.rb', line 89 def self.prompt_optional(name) print "请输入 #{name}(可为空,直接回车表示不设置密码): " $stdin.gets.to_s.strip end |
.prompt_required(name) ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/appship/cache.rb', line 81 def self.prompt_required(name) print "请输入 #{name}: " value = $stdin.gets&.strip raise ConfigurationError, "#{name} 不能为空" if value.to_s.empty? value end |
Instance Method Details
#resolve(project_name: nil, project_dir: Dir.pwd, provider: "pgyer", interactive: true, credential_overrides: {}) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/appship/cache.rb', line 106 def resolve(project_name: nil, project_dir: Dir.pwd, provider: "pgyer", interactive: true, credential_overrides: {}) candidate_name = project_name.to_s.strip if candidate_name.empty? && @entries.length > 1 directory_name = File.basename(File.(project_dir)) candidate_name = directory_name if @entries.any? { |entry| entry["project_name"] == directory_name } end matches = if candidate_name.empty? @entries else @entries.select { |entry| entry["project_name"] == candidate_name } end if matches.length == 1 update_profile!(matches.first, credential_overrides) unless credential_overrides.empty? ensure_provider_credential!(matches.first, provider, interactive: interactive) return matches.first end if matches.empty? available = @entries.filter_map { |entry| entry["project_name"] }.join(", ") raise ConfigurationError, "找不到项目缓存 #{candidate_name.inspect},可用项目: #{available}" end names = matches.filter_map { |entry| entry["project_name"] }.join(", ") raise ConfigurationError, "本机缓存包含多个项目,请使用 --project-name 指定: #{names}" end |
#update_profile!(entry, values) ⇒ Object
132 133 134 135 136 |
# File 'lib/appship/cache.rb', line 132 def update_profile!(entry, values) values.each { |key, value| entry[key.to_s] = value unless value.nil? } persist! entry end |