一、前言
Cocoapods 有很多比较实用的小插件,比如 cocoapods-open ( 执行 pod open 可以直接打开 .xcworkspace 文件),这些插件 gem 都有特定的目录分层。一开始以为自己要从零开始配置,后来发现 cocoapods-plugin 本身就提供了用来创建一个模版工程的 create 命令。 输入以下命令即可创建一个模版工程:
gem install cocoapods- plugins
pod plugins create NAME [ TEMPLATE_URL]
在这个需求中,创建一个 author 子命令,输入:
pod plugins create author
当前路径下会生成 cocoapods-author 目录,其结构如下:
.
├── Gemfile
├── LICENSE. txt
├── README. md
├── Rakefile
├── cocoapods- author. gemspec
├── lib
│ ├── cocoapods- author
│ │ ├── command
│ │ │ └── author. rb
│ │ ├── command. rb
│ │ └── gem_version. rb
│ ├── cocoapods- author. rb
│ └── cocoapods_plugin. rb
└── spec
├── command
│ └── author_spec. rb
└── spec_helper. rb
module Pod
class Command
# This is an example of a cocoapods plugin adding a top- level subcommand
# to the 'pod' command.
#
# You can also create subcommands of existing or new commands. Say you
# wanted to add a subcommand to `list` to show newly deprecated pods,
# ( e. g. `pod list deprecated`) , there are a few things that would need
# to change.
#
# - move this file to `lib/ pod/ command/ list/ deprecated. rb` and update
# the class to exist in the the Pod: : Command: : List namespace
# - change this class to extend from `List` instead of `Command`. This
# tells the plugin system that it is a subcommand of `list`.
# - edit `lib/ cocoapods_plugins. rb` to require this file
#
# @ todo Create a PR to add your plugin to CocoaPods/ cocoapods. org
# in the `plugins. json` file, once your plugin is released.
#
class Author < Command
# pod plugins list 时,展示的概要信息
self . summary = 'Short description of cocoapods- author. '
# -- help / 命令错误时展示的描述信息
self . description = << - DESC
Longer description of cocoapods- author.
DESC
# -- help / 命令错误时展示的参数信息
self . arguments = 'NAME'
def initialize ( argv)
@ name = argv. shift_argument
super
end
# 校验方法(查看文件是否存在等)
def validate!
super
help! 'A Pod name is required.' unless @ name
end
# 运行命令
def run
UI. puts "Add your implementation for the cocoapods-author plugin in #{__FILE__}"
end
end
end
end
如何创建 list 的子命令 deprecated:
移动目标文件至 lib/pod/command/list/deprecated.rb,并且将这个子命令类放进 Pod::Command::List 命名空间中;
在 lib/cocoapods_plugins.rb 中载入该文件。 如果不需要子命令,直接继承 Command 就可以。
二、获取 Podfile untagged 组件名
如下所示的人方法返回没有依赖 tag 的组件哈希,为了简单处理,直接获取 target_definitions 第一个元素的 dependencies 作为工程的依赖进行遍历:
UNTAGGED_FLAGS = [ : path, : git, : branch, : commit]
def load_untageed_dependencies_hash
file_path = Dir. pwd + '/Podfile'
raise % Q[ 没有找到 Podfile,请确认是否在 Podfile 所在文件夹\n] unless File. file? ( file_path)
podfile = Podfile. from_file ( file_path)
dependencies = podfile. to_hash[ 'target_definitions' ] . first[ 'dependencies' ]
# UI. puts dependencies
untageed_dependencies = dependencies. select do | dependency|
tagged = true
if dependency. kind_of? Hash
first = dependency. values. first. first
if first. kind_of? Hash
tagged = first. keys. reduce ( true) do | result, flag|
! UNTAGGED_FLAGS. include? ( flag) & result
end
elsif first. kind_of? String
tagged = true
end
elsif dependency. is_a? ( String)
tagged = true
end
! tagged
end
untageed_dependencies. reduce ( { } ) do | result, dependency|
result. merge ( dependency)
end
end
三、获取本地私有源获取组件的作者
def load_pod_authors ( spec_files)
author_hash = { }
spec_files. each do | file|
if ! file. nil? && File. file? ( file)
podspec = Specification. from_file ( file)
pod_authors = podspec. attributes_hash[ 'authors' ]
if pod_authors. kind_of? Hash
author = pod_authors. keys. first
elsif pod_authors. kind_of? Array
author = pod_authors. first
else
author = pod_authors
end
author = author. downcase
if ! author. nil? && ! podspec. name. nil?
author_hash[ author] = author_hash[ author] . nil? ? [ ] : author_hash[ author]
author_hash[ author] . append ( podspec. name)
end
end
end
author_hash
end
def load_boss_keeper_members
member_hash = { }
@ memebrs_hash. uniq. map. each do | nickname|
reform_memeber_hash_proc = -> nickname, realname do
nickname = nickname. downcase unless ! nickname. nil?
pinyin = Pinyin. t ( nickname, splitter: '' ) . downcase
if pinyin != nickname
member_hash[ nickname] = realname
end
member_hash[ pinyin] = realname
end
if nickname. kind_of? Hash
name = nickname. keys. first. dup. force_encoding ( "UTF-8" )
nickname. values. first. append ( name) . each do | nickname|
reform_memeber_hash_proc. call ( nickname, name)
enddef load_pod_authors ( spec_files)
author_hash = { }
spec_files. each do | file|
if ! file. nil? && File. file? ( file)
podspec = Specification. from_file ( file)
pod_authors = podspec. attributes_hash[ 'authors' ]
if pod_authors. kind_of? Hash
author = pod_authors. keys. first
elsif pod_authors. kind_of? Array
author = pod_authors. first
else
author = pod_authors
end
author = author. downcase
if ! author. nil? && ! podspec. name. nil?
author_hash[ author] = author_hash[ author] . nil? ? [ ] : author_hash[ author]
author_hash[ author] . append ( podspec. name)
end
end
end
author_hash
end
else
reform_memeber_hash_proc. call ( nickname, nickname)
end
end
member_hash
end
如果 @ 组员需要手机号码,那么该部分数据可以从本地的 yaml 文件读取:
file_path = File. join ( File. dirname ( __FILE__ ) , "boss_keeper_members.yaml" )
yaml_hash =
begin
YAML. load_file ( file_path)
rescue Psych: : SyntaxError, Errno: : EACCES, Errno: : ENOENT
{ }
end
@ memebrs_hash = yaml_hash[ 'members' ]
@ mobiles = yaml_hash[ "mobiles" ] . reduce ( { } ) { | result, mobile| result. merge ( mobile) }
由于作者一栏存在用花名、原名、昵称的情况,所以 yaml 文件基本格式如下:
members:
- 青木:
- tripleCC
mobiles:
- 青木:
- 1 xxxxxxx
四、匹配本地存储的组员名
首先匹配是组内组员管理的组件,如果是其它组创建的组件,暂时忽略:
def load_valid_pod_authors_hash
authors_hash = { }
@ pod_authors. each do | name, pods|
member_name = @ boss_keeper_members[ name. downcase]
if ! member_name. nil?
member_name = member_name. downcase
author_pods = authors_hash[ member_name] . nil? ? [ ] : authors_hash[ member_name]
authors_hash[ member_name] = author_pods. append ( pods) . flatten
end
end
authors_hash
end
def load_untageed_dependencies_authors_hash
authors_hash = { }
valid_pod_authors = load_valid_pod_authors_hash
untageed_dependencies_hash = load_untageed_dependencies_hash
untageed_dependencies_hash. keys. each do | pod|
valid_pod_authors. each do | author, pods|
if pods. include? ( pod)
authors_hash[ author] = authors_hash[ author] . nil? ? [ ] : authors_hash[ author]
authors_hash[ author] . append ( pod)
end
end
end
authors_hash
end
五、整合发送
通过 git rev-parse --abbrev-ref HEAD 获取当前所在分支,然后根据作者、组件名、手机号码创建 curl 命令并执行:
def post_message_to_ding_talk
current_branch = `git rev- parse -- abbrev- ref HEAD`. strip
untageed_dependencies_authors_hash = load_untageed_dependencies_authors_hash
untageed_dependencies_authors_hash. each do | author, pods|
content = author + ",#{current_branch}分支" + ",下面的仓库打个版本:" + pods. join ( ',' )
if ! @ mobiles[ author] . nil?
mobile = @ mobiles[ author] . first
end
curl = % Q[
curl 'https:
{
"msgtype" : "text" ,
"text" : {
"content" : "#{content}"
} ,
"at" : {
"atMobiles" : [
"#{mobile}"
] ,
"isAtAll" : false
}
} ']
# UI. puts curl
Kernel. system curl
end
end
如果后续对这个插件进行扩展的话,还应该考虑根据私有源自动生成 Podfile,解决封版时需要手动修改 Podfile 的情况,麻烦而且可能存在把版本号写错的情况。