pindo 5.16.2 → 5.16.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pindo/base/funlog.rb +1 -1
- data/lib/pindo/command/utils/installskills.rb +253 -0
- data/lib/pindo/command/utils.rb +1 -0
- data/lib/pindo/module/android/android_res_helper.rb +6 -4
- data/lib/pindo/module/task/model/nuget/nuget_upload_task.rb +32 -4
- data/lib/pindo/module/xcode/xcode_build_helper.rb +5 -5
- data/lib/pindo/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 061bf75ae3563da24c18d0d4204fdecac9d03011e1493dd4e89b53d9b112d617
|
|
4
|
+
data.tar.gz: a51d17f8a46a767527a34f970657c7cf164511902c28f46e7567b6264de3079f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: efc7584e50c172c78c3e53f45ff97b335f18c60565d02ef8892273c29c253199909c54f590673ab232dfe688a086270d7200097293d7a6c1e0320efd682d2dfb
|
|
7
|
+
data.tar.gz: d0d46c6e9bc600c526e7c3ef2cb4fce1fafd47d39d8e806161d3843cbd40098fac4fecc33fb1f2141cec6d7163ea1ca1ec1642e10f214c7f3beef220bce54e5c
|
data/lib/pindo/base/funlog.rb
CHANGED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
require 'highline/import'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'pindo/base/funlog'
|
|
6
|
+
|
|
7
|
+
module Pindo
|
|
8
|
+
class Command
|
|
9
|
+
class Utils < Command
|
|
10
|
+
class Installskills < Utils
|
|
11
|
+
|
|
12
|
+
self.summary = '安装 Claude Code 技能到本地项目'
|
|
13
|
+
|
|
14
|
+
self.description = <<-DESC
|
|
15
|
+
安装 Claude Code 技能到本地项目。
|
|
16
|
+
|
|
17
|
+
支持功能:
|
|
18
|
+
- 从技能仓库克隆指定技能
|
|
19
|
+
- 支持安装单个或多个技能
|
|
20
|
+
|
|
21
|
+
使用示例:
|
|
22
|
+
pindo utils installskills # 交互式选择仓库安装
|
|
23
|
+
pindo utils installskills skill-name # 从默认仓库安装指定技能
|
|
24
|
+
pindo utils installskills skill1 skill2 # 安装多个技能
|
|
25
|
+
pindo utils installskills --source=https://gitee.com/your/skills.git # 从指定仓库安装
|
|
26
|
+
DESC
|
|
27
|
+
|
|
28
|
+
self.arguments = [
|
|
29
|
+
CLAide::Argument.new('skill_name', false),
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
def self.options
|
|
33
|
+
[
|
|
34
|
+
['--source=URL', '指定技能仓库地址,指定后跳过仓库选择'],
|
|
35
|
+
].concat(super)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def initialize(argv)
|
|
39
|
+
@skill_names = argv.arguments! || []
|
|
40
|
+
@source = argv.option('source')
|
|
41
|
+
|
|
42
|
+
super
|
|
43
|
+
@additional_args = argv.remainder!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def run
|
|
47
|
+
# 确定使用的仓库
|
|
48
|
+
repo_info = determine_repo
|
|
49
|
+
return if repo_info.nil?
|
|
50
|
+
|
|
51
|
+
# 克隆仓库到临时目录
|
|
52
|
+
temp_dir = clone_repo_to_temp(repo_info)
|
|
53
|
+
return if temp_dir.nil?
|
|
54
|
+
|
|
55
|
+
begin
|
|
56
|
+
# 安装 command 和 skills
|
|
57
|
+
install_from_repo(temp_dir, repo_info['skills_repo_name'] || 'custom')
|
|
58
|
+
ensure
|
|
59
|
+
# 清理临时目录
|
|
60
|
+
FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def determine_repo
|
|
67
|
+
# 如果指定了 --source,直接使用
|
|
68
|
+
if @source
|
|
69
|
+
return {
|
|
70
|
+
'skills_repo_name' => 'custom',
|
|
71
|
+
'skills_repo_desc' => '自定义仓库',
|
|
72
|
+
'git_url' => @source
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# 从配置读取仓库列表
|
|
77
|
+
repos = skills_repo_array
|
|
78
|
+
|
|
79
|
+
if repos.empty?
|
|
80
|
+
Funlog.error("未配置技能仓库,请在 ~/.pindo/pindo_common_config/pindo_config.json 中配置 skills_repo_array")
|
|
81
|
+
return nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if repos.length == 1
|
|
85
|
+
Funlog.info("使用默认仓库: #{repos.first['skills_repo_name']}")
|
|
86
|
+
return repos.first
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# 交互式选择仓库
|
|
90
|
+
interactive_select_repo(repos)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def skills_repo_array
|
|
94
|
+
config = pindo_single_config.pindo_user_config_json
|
|
95
|
+
return [] unless config
|
|
96
|
+
|
|
97
|
+
repos = config['skills_repo_array']
|
|
98
|
+
return [] unless repos.is_a?(Array)
|
|
99
|
+
|
|
100
|
+
repos
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def interactive_select_repo(repos)
|
|
104
|
+
Funlog.info("")
|
|
105
|
+
Funlog.info("=============================================================")
|
|
106
|
+
Funlog.info(" 请选择要安装的仓库")
|
|
107
|
+
Funlog.info("=============================================================")
|
|
108
|
+
Funlog.info("")
|
|
109
|
+
|
|
110
|
+
repos.each_with_index do |repo, index|
|
|
111
|
+
name = repo['skills_repo_name'] || "未命名#{index + 1}"
|
|
112
|
+
desc = repo['skills_repo_desc'] || ''
|
|
113
|
+
|
|
114
|
+
# 显示序号和名称
|
|
115
|
+
Funlog.info("[#{index + 1}] #{name}")
|
|
116
|
+
|
|
117
|
+
# 显示描述(如果有)
|
|
118
|
+
unless desc.empty?
|
|
119
|
+
desc.lines.each do |line|
|
|
120
|
+
Funlog.info(" #{line.chomp}")
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# 显示仓库URL(调试模式)
|
|
125
|
+
if ENV['PINDO_DEBUG'] && repo['git_url']
|
|
126
|
+
Funlog.info(" URL: #{repo['git_url']}")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
Funlog.info("")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# 使用 HighLine 获取用户输入
|
|
133
|
+
cli = HighLine.new
|
|
134
|
+
input = cli.ask("请输入序号 (1-#{repos.length}): ")
|
|
135
|
+
|
|
136
|
+
num = input.to_i
|
|
137
|
+
if num >= 1 && num <= repos.length
|
|
138
|
+
selected = repos[num - 1]
|
|
139
|
+
Funlog.info("已选择: #{selected['skills_repo_name']}")
|
|
140
|
+
selected
|
|
141
|
+
else
|
|
142
|
+
Funlog.error("无效选择,请输入 1-#{repos.length} 之间的数字")
|
|
143
|
+
nil
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def clone_repo_to_temp(repo_info)
|
|
148
|
+
url = repo_info['git_url']
|
|
149
|
+
repo_name = repo_info['skills_repo_name'] || 'temp_repo'
|
|
150
|
+
|
|
151
|
+
unless url
|
|
152
|
+
Funlog.error("仓库配置错误,缺少 git_url")
|
|
153
|
+
return nil
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# 创建系统临时目录
|
|
157
|
+
temp_dir = Dir.mktmpdir(['pindo_skills_', "_#{repo_name}"])
|
|
158
|
+
|
|
159
|
+
Funlog.fancyinfo_start("克隆仓库: #{url}...")
|
|
160
|
+
Funlog.info("仓库 URL: #{url}") if ENV['PINDO_DEBUG']
|
|
161
|
+
|
|
162
|
+
# 克隆仓库
|
|
163
|
+
success = system("git clone #{url} #{temp_dir} --quiet 2>/dev/null")
|
|
164
|
+
|
|
165
|
+
unless success && File.exist?(File.join(temp_dir, '.git'))
|
|
166
|
+
Funlog.fancyinfo_error("仓库克隆失败: #{url}")
|
|
167
|
+
FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
|
|
168
|
+
return nil
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
Funlog.fancyinfo_success("仓库克隆完成")
|
|
172
|
+
temp_dir
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def install_from_repo(repo_dir, repo_name)
|
|
176
|
+
installed = false
|
|
177
|
+
|
|
178
|
+
# 安装 commands 目录(合并式拷贝)
|
|
179
|
+
source_commands = File.join(repo_dir, 'commands')
|
|
180
|
+
target_commands = File.expand_path('~/.claude/commands')
|
|
181
|
+
|
|
182
|
+
if File.exist?(source_commands) && File.directory?(source_commands)
|
|
183
|
+
Funlog.info("安装 commands...")
|
|
184
|
+
FileUtils.mkdir_p(target_commands)
|
|
185
|
+
|
|
186
|
+
Dir.glob(File.join(source_commands, '*')).each do |item|
|
|
187
|
+
next if File.basename(item).start_with?('.')
|
|
188
|
+
|
|
189
|
+
target = File.join(target_commands, File.basename(item))
|
|
190
|
+
|
|
191
|
+
if File.directory?(item)
|
|
192
|
+
# 子目录:合并到目标对应子目录
|
|
193
|
+
FileUtils.mkdir_p(target)
|
|
194
|
+
Dir.glob(File.join(item, '*')).each do |sub_item|
|
|
195
|
+
next if File.basename(sub_item).start_with?('.')
|
|
196
|
+
target_sub = File.join(target, File.basename(sub_item))
|
|
197
|
+
FileUtils.rm_rf(target_sub) if File.exist?(target_sub)
|
|
198
|
+
FileUtils.cp_r(sub_item, target_sub)
|
|
199
|
+
end
|
|
200
|
+
else
|
|
201
|
+
# 直接文件:拷贝到目标目录
|
|
202
|
+
FileUtils.rm_f(target) if File.exist?(target)
|
|
203
|
+
FileUtils.cp(item, target)
|
|
204
|
+
end
|
|
205
|
+
Funlog.info(" ✓ #{File.basename(item)}")
|
|
206
|
+
end
|
|
207
|
+
installed = true
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# 安装 skills 目录(合并式拷贝)
|
|
211
|
+
source_skills = File.join(repo_dir, 'skills')
|
|
212
|
+
target_skills = File.expand_path('~/.claude/skills')
|
|
213
|
+
|
|
214
|
+
if File.exist?(source_skills) && File.directory?(source_skills)
|
|
215
|
+
Funlog.info("安装 skills...")
|
|
216
|
+
FileUtils.mkdir_p(target_skills)
|
|
217
|
+
|
|
218
|
+
Dir.glob(File.join(source_skills, '*')).each do |item|
|
|
219
|
+
next if File.basename(item).start_with?('.')
|
|
220
|
+
|
|
221
|
+
target = File.join(target_skills, File.basename(item))
|
|
222
|
+
|
|
223
|
+
if File.directory?(item)
|
|
224
|
+
# 子目录:合并到目标对应子目录
|
|
225
|
+
FileUtils.mkdir_p(target)
|
|
226
|
+
Dir.glob(File.join(item, '*')).each do |sub_item|
|
|
227
|
+
next if File.basename(sub_item).start_with?('.')
|
|
228
|
+
target_sub = File.join(target, File.basename(sub_item))
|
|
229
|
+
FileUtils.rm_rf(target_sub) if File.exist?(target_sub)
|
|
230
|
+
FileUtils.cp_r(sub_item, target_sub)
|
|
231
|
+
end
|
|
232
|
+
else
|
|
233
|
+
# 直接文件:拷贝到目标目录
|
|
234
|
+
FileUtils.rm_f(target) if File.exist?(target)
|
|
235
|
+
FileUtils.cp(item, target)
|
|
236
|
+
end
|
|
237
|
+
Funlog.info(" ✓ #{File.basename(item)}")
|
|
238
|
+
end
|
|
239
|
+
installed = true
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
if installed
|
|
243
|
+
Funlog.fancyinfo_success("技能安装完成: #{repo_name}")
|
|
244
|
+
Funlog.info("安装位置: ~/.claude/")
|
|
245
|
+
else
|
|
246
|
+
Funlog.warning("仓库中未找到 commands 或 skills 目录")
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
data/lib/pindo/command/utils.rb
CHANGED
|
@@ -312,10 +312,12 @@ module Pindo
|
|
|
312
312
|
# 替换所有旧的图标引用为标准名称
|
|
313
313
|
# app_icon -> ic_launcher
|
|
314
314
|
# app_icon_round -> ic_launcher_round
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
content.gsub!(
|
|
318
|
-
content.gsub!(
|
|
315
|
+
# 使用正则表达式精确匹配,避免替换 app_icon_topleft 等变体
|
|
316
|
+
# (?=["'\s>]) 表示后面必须是引号、空格或尖括号(但不包含在替换结果中)
|
|
317
|
+
content.gsub!(/@mipmap\/app_icon_round(?=["'\s>])/, '@mipmap/ic_launcher_round')
|
|
318
|
+
content.gsub!(/@mipmap\/app_icon(?=["'\s>])/, '@mipmap/ic_launcher')
|
|
319
|
+
content.gsub!(/@drawable\/app_icon_round(?=["'\s>])/, '@drawable/ic_launcher_round')
|
|
320
|
+
content.gsub!(/@drawable\/app_icon(?=["'\s>])/, '@drawable/ic_launcher')
|
|
319
321
|
|
|
320
322
|
# 如果内容有变化,保存文件
|
|
321
323
|
if content != original_content
|
|
@@ -164,19 +164,47 @@ module Pindo
|
|
|
164
164
|
# 4. 提交到 JPS 项目
|
|
165
165
|
puts "📋 提交到 JPS 项目..."
|
|
166
166
|
|
|
167
|
+
# 构建请求参数
|
|
168
|
+
request_params = {
|
|
169
|
+
packageUrl: file_url,
|
|
170
|
+
attachFileUrls: []
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if ENV['PINDO_DEBUG']
|
|
174
|
+
puts "[DEBUG] 提交参数:"
|
|
175
|
+
puts "[DEBUG] 项目ID: #{nuget_project['id']}"
|
|
176
|
+
puts "[DEBUG] 项目名称: #{nuget_project['projectName']}"
|
|
177
|
+
puts "[DEBUG] 包URL: #{file_url}"
|
|
178
|
+
puts "[DEBUG] 附件URLs: #{request_params[:attachFileUrls].inspect}"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
puts "++++++ 1 upload_nuget_package" if ENV['PINDO_DEBUG']
|
|
167
182
|
result = jps_client.upload_nuget_package(
|
|
168
183
|
projectId: nuget_project['id'],
|
|
169
|
-
params:
|
|
170
|
-
packageUrl: file_url,
|
|
171
|
-
attachFileUrls: []
|
|
172
|
-
}
|
|
184
|
+
params: request_params
|
|
173
185
|
)
|
|
174
186
|
|
|
187
|
+
if ENV['PINDO_DEBUG']
|
|
188
|
+
puts "[DEBUG] API 响应:"
|
|
189
|
+
puts "[DEBUG] #{result.inspect}"
|
|
190
|
+
end
|
|
191
|
+
|
|
175
192
|
if result && (result['code'] == 0 || result['code'] == 200)
|
|
176
193
|
puts "✅ 提交成功"
|
|
177
194
|
print_upload_result(result)
|
|
178
195
|
else
|
|
179
196
|
error_msg = result['message'] || result['msg'] || '未知错误'
|
|
197
|
+
error_code = result['code']
|
|
198
|
+
|
|
199
|
+
puts "[ERROR] 提交失败详情:"
|
|
200
|
+
puts "[ERROR] 错误代码: #{error_code}"
|
|
201
|
+
puts "[ERROR] 错误消息: #{error_msg}"
|
|
202
|
+
|
|
203
|
+
if ENV['PINDO_DEBUG']
|
|
204
|
+
puts "[DEBUG] 完整响应内容:"
|
|
205
|
+
puts "[DEBUG] #{JSON.pretty_generate(result)}" rescue puts "[DEBUG] #{result.inspect}"
|
|
206
|
+
end
|
|
207
|
+
|
|
180
208
|
raise Informative, "提交失败: #{error_msg}"
|
|
181
209
|
end
|
|
182
210
|
end
|
|
@@ -514,7 +514,7 @@ module Pindo
|
|
|
514
514
|
|
|
515
515
|
project_build_platform = project_obj.root_object.build_configuration_list.get_setting("SDKROOT")["Release"]
|
|
516
516
|
main_target = project_obj.targets.select { |target| target.product_type.include?(Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application]) }.first
|
|
517
|
-
provisioning_profile_name = main_target.build_configurations.first.build_settings['PROVISIONING_PROFILE_SPECIFIER'].downcase
|
|
517
|
+
provisioning_profile_name = main_target.build_configurations.first.build_settings['PROVISIONING_PROFILE_SPECIFIER'].downcase
|
|
518
518
|
|
|
519
519
|
# 确定构建类型和 iCloud 环境
|
|
520
520
|
build_type = "app-store"
|
|
@@ -522,10 +522,10 @@ module Pindo
|
|
|
522
522
|
|
|
523
523
|
if !project_build_platform.nil? && project_build_platform.eql?("macosx")
|
|
524
524
|
# macOS 平台
|
|
525
|
-
if provisioning_profile_name.include?("development")
|
|
525
|
+
if provisioning_profile_name.downcase.include?("development")
|
|
526
526
|
build_type = "development"
|
|
527
527
|
icloud_env = "Development"
|
|
528
|
-
elsif provisioning_profile_name.include?("appstore")
|
|
528
|
+
elsif provisioning_profile_name.downcase.include?("appstore")
|
|
529
529
|
build_type = "mac-application"
|
|
530
530
|
icloud_env = "Production"
|
|
531
531
|
else
|
|
@@ -534,10 +534,10 @@ module Pindo
|
|
|
534
534
|
end
|
|
535
535
|
else
|
|
536
536
|
# iOS 平台
|
|
537
|
-
if provisioning_profile_name.include?("adhoc")
|
|
537
|
+
if provisioning_profile_name.downcase.include?("adhoc")
|
|
538
538
|
build_type = "ad-hoc"
|
|
539
539
|
icloud_env = "Development"
|
|
540
|
-
elsif provisioning_profile_name.include?("development")
|
|
540
|
+
elsif provisioning_profile_name.downcase.include?("development")
|
|
541
541
|
build_type = "development"
|
|
542
542
|
icloud_env = "Development"
|
|
543
543
|
else
|
data/lib/pindo/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pindo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.16.
|
|
4
|
+
version: 5.16.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- wade
|
|
@@ -112,7 +112,7 @@ dependencies:
|
|
|
112
112
|
version: '2.0'
|
|
113
113
|
- - ">="
|
|
114
114
|
- !ruby/object:Gem::Version
|
|
115
|
-
version: 2.0.
|
|
115
|
+
version: 2.0.3
|
|
116
116
|
type: :runtime
|
|
117
117
|
prerelease: false
|
|
118
118
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -122,7 +122,7 @@ dependencies:
|
|
|
122
122
|
version: '2.0'
|
|
123
123
|
- - ">="
|
|
124
124
|
- !ruby/object:Gem::Version
|
|
125
|
-
version: 2.0.
|
|
125
|
+
version: 2.0.3
|
|
126
126
|
- !ruby/object:Gem::Dependency
|
|
127
127
|
name: rqrcode
|
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -355,6 +355,7 @@ files:
|
|
|
355
355
|
- lib/pindo/command/utils/encrypt.rb
|
|
356
356
|
- lib/pindo/command/utils/fabric.rb
|
|
357
357
|
- lib/pindo/command/utils/icon.rb
|
|
358
|
+
- lib/pindo/command/utils/installskills.rb
|
|
358
359
|
- lib/pindo/command/utils/renewcert.rb
|
|
359
360
|
- lib/pindo/command/utils/renewproj.rb
|
|
360
361
|
- lib/pindo/command/utils/repoinit.rb
|