From 6e61455c904047d725775e8021f28e92bb84f7d0 Mon Sep 17 00:00:00 2001 From: Rustam Zaitov Date: Thu, 3 Oct 2013 17:27:48 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B0=D1=82=D1=87=D0=B8=D0=BD=D0=B3=20In?= =?UTF-8?q?fo=20Plist'=D0=B0=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=BE=20=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD=D0=B4=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/commands/build_command.py | 53 ++++++++++++++++ scripts/commands/patch_csproj_command.py | 48 +++++++++++++++ scripts/commands/patch_infoplist_command.py | 15 +---- scripts/settings.py | 14 ++++- scripts/utils/csproj/__init__.py | 1 + scripts/utils/csproj/patcher.py | 67 +++++++++++++++++++++ 6 files changed, 182 insertions(+), 16 deletions(-) create mode 100644 scripts/commands/patch_csproj_command.py create mode 100644 scripts/utils/csproj/__init__.py create mode 100644 scripts/utils/csproj/patcher.py diff --git a/scripts/commands/build_command.py b/scripts/commands/build_command.py index 62926c8..a957e1b 100644 --- a/scripts/commands/build_command.py +++ b/scripts/commands/build_command.py @@ -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 diff --git a/scripts/commands/patch_csproj_command.py b/scripts/commands/patch_csproj_command.py new file mode 100644 index 0000000..06200b8 --- /dev/null +++ b/scripts/commands/patch_csproj_command.py @@ -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']) diff --git a/scripts/commands/patch_infoplist_command.py b/scripts/commands/patch_infoplist_command.py index bf3d248..1f05c31 100644 --- a/scripts/commands/patch_infoplist_command.py +++ b/scripts/commands/patch_infoplist_command.py @@ -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:] diff --git a/scripts/settings.py b/scripts/settings.py index a21ccef..29f2742 100644 --- a/scripts/settings.py +++ b/scripts/settings.py @@ -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 diff --git a/scripts/utils/csproj/__init__.py b/scripts/utils/csproj/__init__.py new file mode 100644 index 0000000..cc31abc --- /dev/null +++ b/scripts/utils/csproj/__init__.py @@ -0,0 +1 @@ +__author__ = 'rzaitov' diff --git a/scripts/utils/csproj/patcher.py b/scripts/utils/csproj/patcher.py new file mode 100644 index 0000000..66564a2 --- /dev/null +++ b/scripts/utils/csproj/patcher.py @@ -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 \ No newline at end of file