Патчинг Info Plist'а реализовано на коммандах

This commit is contained in:
Rustam Zaitov 2013-10-03 17:27:48 +04:00
parent 93fff46485
commit 6e61455c90
6 changed files with 182 additions and 16 deletions

View File

@ -1,3 +1,56 @@
class BuildCommand:
def SetCommandPrefix(self, value):
self._command_prefix = value
self._cmd_prefix_len = len(self._command_prefix)
self._prefix_name= 'prefix'
self._group_name= 'group'
self._key_name = 'key'
def __init__(self, config, cmd_prefix, separator='-'):
self._separator = separator
self._config = config
self.SetCommandPrefix(cmd_prefix)
def ParseConfig(self):
return None
def FetchAllKeysFromConfig(self):
all_keys = []
for k in self._config:
k.startswith(self._command_prefix)
all_keys.append(k)
return all_keys
def ParseKeyToken(self, key_token):
# csproj-AppName-Key
identifiers = key_token.split(self._separator)
result = {
self._prefix_name: identifiers[0],
self._group_name: identifiers[1],
self._key_name: identifiers[2]
}
return result
def ParseValueFromToken(self, value_token):
value = value_token
if value_token.startswith('@'):
key = value_token[1:]
value = self._config[key]
return value
def Execute(self):
return None

View File

@ -0,0 +1,48 @@
import commands.build_command as bcmd
import utils.csproj.patcher as csproj
import utils.PathConverter.path_converter as path
class PatchCsproj(bcmd.BuildCommand):
def __init__(self, config):
bcmd.BuildCommand.__init__(self, config, 'csproj-')
self._patch_settings = {}
def ParseConfig(self):
csproj_keys = self.FetchAllKeysFromConfig()
self.FillPatchSettings(csproj_keys)
def FillPatchSettings(self, key_tokens):
for key_token in key_tokens:
key_info = self.ParseKeyToken(key_token)
project_name = key_info[self._group_name]
key = key_info[self._key_name]
value = self.ParseValueFromToken(self._config[key_token])
project_settings = self.FetchSettingForProject(project_name)
project_settings[key] = value
def FetchSettingForProject(self, project_name):
project_settings = self._patch_settings.get(project_name, None)
if project_settings is None:
project_settings = {}
self._patch_settings[project_name] = project_settings
return project_settings
def Execute(self):
converter = path.PathConverter(self._config['sln_path'])
for project_name in self._patch_settings.keys():
project_settings = self._patch_settings[project_name]
self.PatchProject(project_settings, converter)
def PatchProject(self, project_settings, path_converter):
csproj_rel_path = project_settings['rel_path']
csproj_abs_path = path_converter.Convert(csproj_rel_path)
patcher = csproj.Patcher(csproj_abs_path)
patcher.AddOrReplace(project_settings, self._config['sln_config'])

View File

@ -4,11 +4,8 @@ import utils.infoplist.patcher as plist
class PatchInfoPlist(bcmd.BuildCommand):
_command_prefix = 'info_plist_'
_cmd_prefix_len = len(_command_prefix)
def __init__(self, config):
self._config = config
bcmd.BuildCommand.__init__(self, config, 'plist-')
self._info_plist_rel_path = None
self._plist_dict = {}
@ -37,19 +34,11 @@ class PatchInfoPlist(bcmd.BuildCommand):
def AddValueFor(self, conf_key):
value_token = self._config[conf_key]
value = self.ParseValueToken(value_token)
value = self.ParseValueFromToken(value_token)
k = self.ParsePlistKeyFrom(conf_key)
self._plist_dict[k] = value
def ParseValueToken(self, value_token):
value = value_token
if value_token.startswith('@'):
key = value_token[1:]
value = self._config[key]
return value
def ParsePlistKeyFrom(self, config_key):
return config_key[PatchInfoPlist._cmd_prefix_len:]

View File

@ -30,9 +30,17 @@ ios_development_root = {
'projects_to_exclude': ['NotCompileApp'],
# patch_info_plist
'info_plist_rel_path': 'BuildSample/Info.plist',
'info_plist_CFBundleVersion': '@version', # set CFBundleVersion
'info_plist_CFBundleDisplayName': '@app_name', # set CFBundleDisplayName
'plist-CoolApp_rel_path': 'BuildSample/Info.plist',
'plist-CoolApp_CFBundleVersion': '@version', # set CFBundleVersion
'plist-CoolApp_CFBundleDisplayName': '@app_name', # set CFBundleDisplayName
# test flight command section
'tf_CoolApp_output': 'ipa',
# patch_csproj
'csproj-CoolApp-rel_path': 'BuildSample/CoolApp.csproj',
'csproj-CoolApp-CodesignProvision': '@codesign_provision',
'csproj-CoolApp-CodesignKey': '@codesign_key',
'build_steps':[
# before build

View File

@ -0,0 +1 @@
__author__ = 'rzaitov'

View File

@ -0,0 +1,67 @@
import xml.etree.ElementTree as eT
class Patcher:
def __init__(self, csproj_abs_path):
self._csproj_abs_path = csproj_abs_path
def FetchPropertyGroup(self, sln_config_name):
tree = eT.parse(self._csproj_abs_path)
project_element = tree.getroot()
property_group = self.GetPropertyGroupBy(project_element, sln_config_name)
return property_group
def GetPropertyGroupBy(self, project_element, config_name):
property_groups = project_element.findall('PropertyGroup')
prop_group = None
for pg_elem in property_groups:
atr_value = pg_elem.get('Condition')
is_fit = self.IsValueFitFor(config_name, atr_value)
if is_fit:
prop_group = pg_elem
break
return prop_group
def Remove(self, tag_names, sln_config_name):
property_group = self.FetchPropertyGroup(sln_config_name)
self.RemoveTagsFor(property_group, tag_names)
def AddOrReplace(self, key_value_dict, sln_config_name):
property_group = self.FetchPropertyGroup(sln_config_name)
self.AddOrReplaceTagsFor(property_group, key_value_dict)
def IsValueFitFor(self, config_name, condition_attr_value):
result = config_name in condition_attr_value
return result
def RemoveTagsFor(self, property_group_element, tag_names):
for tn in tag_names:
elem_to_remove = property_group_element.find(tn)
if elem_to_remove is not None:
property_group_element.remove(elem_to_remove)
def AddOrReplaceTagsFor(self, property_group_element, key_value_dict):
for k in key_value_dict:
v = key_value_dict[k]
self.AppendOrReplaceValueByKey(k, v, property_group_element)
def AppendOrReplaceValueByKey(self, tag_name, value, property_group_element):
tag = property_group_element.find(tag_name)
if tag is None:
tag = eT.Element(tag_name)
property_group_element.append(tag)
tag.text = value