Class: UniPod::Server::CacheManager
- Inherits:
-
Object
- Object
- UniPod::Server::CacheManager
- Defined in:
- lib/unipod/server/cache_manager.rb
Overview
管理本地缓存和索引仓库
Constant Summary collapse
- DEFAULT_CACHE_DIR =
File.join(Dir.home, 'Library', 'Caches', 'UniPod')
- DEFAULT_INDEX_REPO_DIR =
File.join(DEFAULT_CACHE_DIR, 'scoped')
- DEFAULT_PACKAGES_DIR =
File.join(DEFAULT_CACHE_DIR, 'packages')
- DEFAULT_TARBALLS_DIR =
File.join(DEFAULT_CACHE_DIR, 'tarballs')
- PACKAGE_TYPE_UNITY =
增加Unity和NPM的包类型常量
'unity'.freeze
- PACKAGE_TYPE_NPM =
'npm'.freeze
Instance Method Summary collapse
-
#extract_repo_name_from_url(url) ⇒ Object
从Git URL中提取仓库名称.
-
#get_all_packages ⇒ Object
获取所有包的信息.
-
#get_package_info(package_name) ⇒ Object
获取包信息.
-
#get_package_tarball(package_name, tarball_name) ⇒ Object
获取包的压缩文件.
-
#get_package_versions(package_name) ⇒ Object
获取包的版本信息.
-
#initialize(options = {}) ⇒ CacheManager
constructor
A new instance of CacheManager.
-
#load_index_repos_from_config ⇒ Object
从Unity的manifest.json文件中读取索引库配置.
-
#refresh_cache ⇒ Object
刷新缓存的公开方法,确保在private方法列表之前定义.
-
#search_packages(query) ⇒ Object
搜索包.
Constructor Details
#initialize(options = {}) ⇒ CacheManager
Returns a new instance of CacheManager.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/unipod/server/cache_manager.rb', line 25 def initialize( = {}) @cache_dir = [:cache_dir] || detect_cache_dir @index_repo_dir = [:index_repo_dir] || File.join(@cache_dir, 'scoped') @packages_dir = File.join(@cache_dir, 'packages') @tarballs_dir = File.join(@cache_dir, 'tarballs') @verbose = [:verbose] || false @index_repos = [] @cache = {} # 内存缓存 @last_update_time = {} # 最后更新时间 @index_updated = false # 索引是否已更新 @package_type_cache = {} # 包类型缓存 # 确保缓存目录存在 FileUtils.mkdir_p(@cache_dir) FileUtils.mkdir_p(@index_repo_dir) FileUtils.mkdir_p(@packages_dir) FileUtils.mkdir_p(@tarballs_dir) # 从配置中读取索引库 load_index_repos_from_config # 初始化索引库 update_index_repos end |
Instance Method Details
#extract_repo_name_from_url(url) ⇒ Object
从Git URL中提取仓库名称
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/unipod/server/cache_manager.rb', line 93 def extract_repo_name_from_url(url) # 处理URL格式 # 示例: https://gitee.com/goodunitylib/JoyUnityLibIndex.git -> JoyUnityLibIndex # 示例: [email protected]:user/repo.git -> repo # 示例: https://github.com/user/repo -> repo if url.nil? || url.empty? return 'default_repo' end # 移除尾部的.git(如果有) url = url.sub(/\.git\z/, '') # 处理不同格式的URL if url.include?('/') # 处理https://格式或git://格式 repo_name = url.split('/').last elsif url.include?(':') # 处理git@格式 repo_name = url.split(':').last.split('/').last else # 无法解析时使用默认名称 repo_name = 'default_repo' end # 确保名称不包含特殊字符 repo_name.gsub(/[^a-zA-Z0-9_-]/, '_') end |
#get_all_packages ⇒ Object
获取所有包的信息
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/unipod/server/cache_manager.rb', line 180 def get_all_packages UI.puts 'CacheManager: 获取所有包' if @verbose # 检查索引是否已更新且缓存不为空 if is_index_updated? && !@cache.empty? UI.puts "CacheManager: 返回缓存中的 #{@cache.size} 个包" if @verbose # 确保返回格式化的结果 return format_packages_response(@cache.values) end packages = {} # 获取存储库目录中的package.json文件 package_files = Dir.glob(File.join(@index_repo_dir, '**/package.json')) spec_files = Dir.glob(File.join(@index_repo_dir, '**/spec.json')) UI.puts "CacheManager: 找到 #{package_files.size} 个package.json文件" if @verbose UI.puts "CacheManager: 找到 #{spec_files.size} 个spec.json文件" if @verbose # 处理所有找到的package.json文件 package_files.each do |package_file| begin package_data = JSON.parse(File.read(package_file)) package_name = package_data['name'] if package_name.nil? || package_name.empty? UI.puts "CacheManager: 忽略没有名称的包: #{package_file}" if @verbose next end UI.puts "CacheManager: 处理包 #{package_name}" if @verbose packages[package_name] = package_data rescue JSON::ParserError => e UI.puts "CacheManager: 解析错误 #{package_file}: #{e.}" if @verbose rescue => e UI.puts "CacheManager: 处理 #{package_file} 时出错: #{e.}" if @verbose end end # 处理所有找到的spec.json文件 spec_files.each do |spec_file| begin spec_data = JSON.parse(File.read(spec_file)) package_name = spec_data['name'] if package_name.nil? || package_name.empty? UI.puts "CacheManager: 忽略没有名称的规格: #{spec_file}" if @verbose next end if packages.key?(package_name) # 合并spec.json中的信息到现有包 packages[package_name] = packages[package_name].merge(spec_data) UI.puts "CacheManager: 合并规格到包 #{package_name}" if @verbose else # 添加新包 packages[package_name] = spec_data UI.puts "CacheManager: 添加规格作为新包 #{package_name}" if @verbose end rescue JSON::ParserError => e UI.puts "CacheManager: 解析错误 #{spec_file}: #{e.}" if @verbose rescue => e UI.puts "CacheManager: 处理 #{spec_file} 时出错: #{e.}" if @verbose end end # 如果没有找到包,添加示例包以确保功能正常运行 if packages.empty? UI.puts "CacheManager: 警告 - 未找到有效的包,创建示例包" if @verbose # 创建并添加示例包 example_package = create_example_package packages[example_package['name']] = example_package UI.puts "CacheManager: 添加了示例包: #{example_package['name']}" if @verbose end # 更新缓存 @cache = packages @index_updated = true # 使用format_packages_response格式化返回结果 formatted_result = format_packages_response(@cache.values) UI.puts "CacheManager: 返回 #{formatted_result['objects'].size} 个包" if @verbose return formatted_result end |
#get_package_info(package_name) ⇒ Object
获取包信息
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/unipod/server/cache_manager.rb', line 123 def get_package_info(package_name) # 从缓存中获取 if @cache.key?(package_name) return @cache[package_name] end ensure_index_updated UI.puts "获取包信息: #{package_name}" if @verbose # 从索引库中查找包信息 @index_repos.each do |repo| repo_dir = get_repo_dir(repo[:name]) specs_dir = File.join(repo_dir, 'Specs') # 首先检查Specs目录(CocoaPods结构) package_dir = File.join(specs_dir, package_name) if Dir.exist?(package_dir) # 查找最新版本 version_dirs = Dir.glob(File.join(package_dir, '*')).select { |d| File.directory?(d) } if version_dirs.any? # 获取最新版本 latest_version_dir = version_dirs.sort_by { |d| Gem::Version.new(File.basename(d)) rescue '0.0.0' }.last spec_path = File.join(latest_version_dir, 'spec.json') if File.exist?(spec_path) begin spec = JSON.parse(File.read(spec_path)) package_info = convert_spec_to_package(spec) processed_info = ensure_package_structure(package_info) @cache[package_name] = processed_info return processed_info rescue => e UI.puts "解析spec.json错误: #{e.}" if @verbose end end end end # 向后兼容:检查package.json package_path = File.join(repo_dir, package_name, 'package.json') if File.exist?(package_path) begin package_info = JSON.parse(File.read(package_path)) processed_info = ensure_package_structure(package_info) @cache[package_name] = processed_info return processed_info rescue => e UI.puts "解析package.json错误: #{e.}" if @verbose end end end nil end |
#get_package_tarball(package_name, tarball_name) ⇒ Object
获取包的压缩文件
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/unipod/server/cache_manager.rb', line 292 def get_package_tarball(package_name, tarball_name) UI.puts "获取包压缩文件: #{package_name} - #{tarball_name}" if @verbose # 查找缓存的压缩文件 tarball_path = File.join(@tarballs_dir, package_name, tarball_name) if File.exist?(tarball_path) UI.puts "使用缓存的压缩文件: #{tarball_path}" if @verbose return tarball_path end UI.puts "缓存中没有找到压缩文件,尝试从Git仓库构建" if @verbose # 获取包信息 package_info = get_package_info(package_name) unless package_info UI.puts "未找到包信息: #{package_name}" if @verbose return nil end # 检查是否有Git仓库信息 if package_info['git'] && package_info['git']['url'] git_url = package_info['git']['url'] git_tag = package_info['git']['tag'] || package_info['version'] git_branch = package_info['git']['branch'] || 'main' UI.puts "从Git仓库构建压缩包: #{git_url} (tag: #{git_tag}, branch: #{git_branch})" if @verbose # 调用克隆并构建包的方法 if clone_and_build_package(package_name, git_url, git_tag, git_branch) # 检查是否成功生成压缩文件 if File.exist?(tarball_path) UI.puts "成功构建压缩包: #{tarball_path}" if @verbose return tarball_path end end end # 如果还是没有找到,尝试从索引库中查找现有的tgz文件 @index_repos.each do |repo| repo_dir = get_repo_dir(repo[:name]) pkg_dir = File.join(repo_dir, package_name) # 检查是否有对应的压缩文件 tarball_paths = Dir.glob(File.join(pkg_dir, "*.tgz")) if !tarball_paths.empty? # 保存到缓存 FileUtils.mkdir_p(File.dirname(tarball_path)) FileUtils.cp(tarball_paths.first, tarball_path) return tarball_path end end nil end |
#get_package_versions(package_name) ⇒ Object
获取包的版本信息
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/unipod/server/cache_manager.rb', line 269 def get_package_versions(package_name) UI.puts "获取包版本信息: #{package_name}" if @verbose package_info = get_package_info(package_name) return nil unless package_info versions = {} package_info['versions'].each do |version, info| versions[version] = ensure_package_structure(info) end { 'name' => package_name, 'versions' => versions, 'time' => { 'modified' => Time.now.iso8601, 'created' => Time.now.iso8601 }, 'dist-tags' => package_info['dist-tags'] || { 'latest' => package_info['version'] } } end |
#load_index_repos_from_config ⇒ Object
从Unity的manifest.json文件中读取索引库配置
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/unipod/server/cache_manager.rb', line 61 def load_index_repos_from_config # 从Config模块获取配置的索引库 config_repos = Config.index_repos || [] # 将配置的索引库添加到索引库列表 config_repos.each do |repo| if repo[:package_index_url] @index_repos << repo end end # 如果没有配置索引库,使用默认索引库 if @index_repos.empty? # 默认Git URL default_git_url = 'https://gitee.com/goodunitylib/JoyUnityLibIndex.git' # 从URL中提取仓库名称 repo_name = extract_repo_name_from_url(default_git_url) @index_repos = [ { name: repo_name, url: default_git_url, package_index_url: default_git_url } ] end UI.puts "加载了#{@index_repos.size}个索引库配置" if @verbose end |
#refresh_cache ⇒ Object
刷新缓存的公开方法,确保在private方法列表之前定义
51 52 53 54 55 56 57 58 |
# File 'lib/unipod/server/cache_manager.rb', line 51 def refresh_cache UI.puts "刷新包缓存..." if @verbose @index_updated = false @cache = {} # 清空缓存 get_all_packages # 重新加载所有包 UI.puts "包缓存已刷新,共发现#{@cache.size}个包" if @verbose true end |
#search_packages(query) ⇒ Object
搜索包
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/unipod/server/cache_manager.rb', line 348 def search_packages(query) # 确保索引是最新的 ensure_index_updated UI.puts "搜索包: #{query}" if @verbose # 获取所有包信息 all_packages = get_all_packages # 如果没有查询,返回所有包 if query.nil? || query.empty? return all_packages end # 过滤包 filtered_packages = all_packages['objects'].select do |obj| package = obj['package'] name_matches_query?(package['name'], query) || (package['description'] && package['description'].downcase.include?(query.downcase)) || (package['keywords'] && package['keywords'].any? { |k| k.downcase.include?(query.downcase) }) end # 为空结果时尝试更灵活的匹配 if filtered_packages.empty? # 尝试作用域匹配 if query.include?('.') scope = query.split('.').first filtered_packages = all_packages['objects'].select do |obj| package = obj['package'] package['name'].start_with?(scope) end end # 尝试前缀匹配 if filtered_packages.empty? filtered_packages = all_packages['objects'].select do |obj| package = obj['package'] package['name'].include?(query.downcase) end end end { 'objects' => filtered_packages, 'total' => filtered_packages.size, 'time' => all_packages['time'] } end |