Merge branch 'BS-41'

This commit is contained in:
rzaitov 2013-11-13 14:24:27 +04:00
commit 6c231fa905
31 changed files with 330 additions and 139 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -70,9 +70,6 @@
<Reference Include="System.Core" />
<Reference Include="monotouch" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
</ItemGroup>
@ -88,4 +85,13 @@
<Name>Domain</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Content\" />
</ItemGroup>
<ItemGroup>
<BundleResource Include="Content\Icons\icon-iphone-staging.png" />
<BundleResource Include="Content\Icons\icon-iphone-staging%402x.png" />
<BundleResource Include="Content\Icons\icon-iphone.png" />
<BundleResource Include="Content\Icons\icon-iphone%402x.png" />
</ItemGroup>
</Project>

View File

@ -16,5 +16,10 @@
<string>com.touchin.buildscript</string>
<key>CFBundleVersion</key>
<string>0.0.0</string>
<key>CFBundleIconFiles</key>
<array>
<string>Content/Icons/icon-iphone@2x</string>
<string>Content/Icons/icon-iphone</string>
</array>
</dict>
</plist>

View File

@ -9,4 +9,6 @@ inside 'BuildSample/BuildSample/CoolApp.csproj' set OutputPath to 'Output' for '
inside 'BuildSample/BuildSample/Info.plist' set CFBundleVersion to '{@version}'
inside 'BuildSample/BuildSample/Info.plist' set CFBundleDisplayName to 'CoolApp'
inside 'BuildSample/BuildSample/Info.plist' set CFBundleIconFiles with values '{@icons}'
install profile 'BuildSample/BuildSample/Profiles/8F606DAE-F9C9-4A19-8EFF-34B990D76C28.mobileprovision'

View File

@ -0,0 +1,31 @@
from commands.PatchInfoPlistCommand import PatchInfoPlistCommand
from parsers.InsideParser.InsideSetArrayParser import InsideSetArrayParser
class PatchInfoPlistArrayCommandBuilder:
def __init__(self):
pass
def isPatchInfoPlist(self, line):
assert line is not None
parser = self.createParser()
isValid = parser.isValidLine(line)
return isValid
def getCommandFor(self, line):
parser = self.createParser()
result = parser.parseLine(line)
path = result[0]
key = result[1]
value = parser.values
command = PatchInfoPlistCommand(path, key, value)
return command
def createParser(self):
parser = InsideSetArrayParser('plist')
return parser

View File

@ -11,13 +11,13 @@ class PatchInfoplistCommandBuilder:
def isPatchInfoPlist(self, line):
assert line is not None
parser = self.__createParser()
parser = self.createParser()
isValid = parser.isValidLine(line)
return isValid
def getCommandFor(self, line):
parser = self.__createParser()
parser = self.createParser()
result = parser.parseLine(line)
path = result[0]
@ -27,7 +27,7 @@ class PatchInfoplistCommandBuilder:
command = PatchInfoPlistCommand(path, key, value)
return command
def __createParser(self):
def createParser(self):
parser = InsideSetParser('plist')
return parser

View File

@ -5,6 +5,7 @@ from CommandBuilders.DeleteBackupCommandBuilder import DeleteBackupCommandBuilde
from CommandBuilders.InstallProfileCommandBuilder import InstallProfileCommandBuilder
from CommandBuilders.MakeDirsCommandBuilder import MakeDirsCommandBuilder
from CommandBuilders.PatchCsprojCommandBuilder import PatchCsprojCommandBuilder
from CommandBuilders.PatchInfoPlistArrayCommandBuilder import PatchInfoPlistArrayCommandBuilder
from CommandBuilders.PatchInfoplistCommandBuilder import PatchInfoplistCommandBuilder
from CommandBuilders.RemoveProjectCommandBuilder import RemoveProjectCommandBuilder
from CommandBuilders.RestoreBackupCommandBuilder import RestoreBackupCommandBuilder
@ -29,6 +30,7 @@ class StepsRunner:
self.createDirs = MakeDirsCommandBuilder()
self.patchCsproj = PatchCsprojCommandBuilder()
self.patchInfoPlist = PatchInfoplistCommandBuilder(self.valueProvider)
self.patchInfoPlistArray = PatchInfoPlistArrayCommandBuilder()
self.copyBuilder = CopyCommandBuilder()
self.testflightBuilder = TestflightCommandBuilder()
self.installProfileBuilder = InstallProfileCommandBuilder()
@ -66,6 +68,8 @@ class StepsRunner:
cmd = self.patchCsproj.getCommandFor(line)
elif self.patchInfoPlist.isPatchInfoPlist(line):
cmd = self.patchInfoPlist.getCommandFor(line)
elif self.patchInfoPlistArray.isPatchInfoPlist(line):
cmd = self.patchInfoPlistArray.getCommandFor(line)
elif self.copyBuilder.isCopy(line):
cmd =self.copyBuilder.getCommandFor(line)
elif self.restoreFromBackupBuilder.isRestoreBackup(line):

View File

@ -0,0 +1,8 @@
from CommandBuilders.PatchInfoPlistArrayCommandBuilder import PatchInfoPlistArrayCommandBuilder
line = "inside 'BuildSample/BuildSample/Info.plist' set UISupportedInterfaceOrientations with values 'value1:value2:value3'"
cmdBuilder = PatchInfoPlistArrayCommandBuilder()
command = cmdBuilder.getCommandFor(line)
command.execute()

View File

@ -27,7 +27,7 @@ another bla
<include 'paht2'>
yet another bla"""
processedText = self.includeText.processText(text)
processedText = self.includeText.processText(text, self.includeText)
expected = """
bla bla

View File

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

View File

@ -0,0 +1,46 @@
import unittest
from Tests.UnitTests.LineParserTestCaseBase import LineParserTestCaseBase
from parsers.InsideParser.InsideSetArrayParser import InsideSetArrayParser
class TestInsideSetArrayParser(LineParserTestCaseBase):
_validSingleValueTest = "inside 'my.txt' set KEY with values 'value1'"
_validMultiValueTest = "inside 'my.txt' set KEY with values 'value1:value2:value3'"
def setUp(self):
self.textParser = InsideSetArrayParser('txt')
def test_isValid(self):
self.isValidText(TestInsideSetArrayParser._validSingleValueTest)
self.isValidText(TestInsideSetArrayParser._validMultiValueTest)
self.isValidText("inside 'my.txt' set KEY with values 'value1:value2:value3'")
def test_isNotValid(self):
self.isNotValidText("inside 'my.sln' set KEY with values 'value1'")
self.isNotValidText("inside 'my.sln' set KEY with values 'value1:value2'")
self.isNotValidText("inside 'my.txt' set KEY with values 'value1' ")
self.isNotValidText("inside 'my.txt' set KEY with values 'value1' bla bla")
def test_parse(self):
self.checkParse(TestInsideSetArrayParser._validSingleValueTest, 'my.txt', 'KEY', 'value1')
self.checkParse(TestInsideSetArrayParser._validMultiValueTest, 'my.txt', 'KEY', 'value1:value2:value3')
def test_values(self):
self.checkValues(TestInsideSetArrayParser._validSingleValueTest, ['value1'])
self.checkValues(TestInsideSetArrayParser._validMultiValueTest, ['value1', 'value2', 'value3'])
def checkParse(self, line, filePath, key, value):
result = self.textParser.parseLine(line)
self.assertEqual(filePath, result[0])
self.assertEqual(key, result[1])
self.assertEqual(value, result[2])
def checkValues(self, text, expectedValues):
self.textParser.parseLine(text)
self.assertEqual(len(expectedValues), len(self.textParser.values))
for v in self.textParser.values:
self.assertTrue(v in expectedValues)

View File

@ -8,12 +8,12 @@ class TestCommentRemover(unittest.TestCase):
def test_startsWithComment(self):
line = '# this line is comment'
newLine = self.commentRemover.processText(line)
newLine = self.commentRemover.processText(line, self.commentRemover)
self.assertEqual('', newLine)
def test_containsComment(self):
line = 'this line contains # a comment'
newLine = self.commentRemover.processText(line)
newLine = self.commentRemover.processText(line, self.commentRemover)
self.assertEqual('this line contains ', newLine)

View File

@ -21,6 +21,6 @@ class TestMacroResolver(unittest.TestCase):
def test_resolveLine(self):
line = '{@key1} bla {@some_name} version: {@version}'
newLine = self.macroResolver.processText(line)
newLine = self.macroResolver.processText(line, self.macroResolver)
self.assertEqual('hello world bla another name version: 1.2.3', newLine)

View File

@ -8,6 +8,6 @@ class TestStripper(unittest.TestCase):
def test_stripLine(self):
line = ' \tSome text \t\r\n'
newLine = self.stripper.processText(line)
newLine = self.stripper.processText(line, self.stripper)
self.assertEqual('Some text', newLine)

View File

@ -0,0 +1,18 @@
from unittest.case import TestCase
class LineParserTestCaseBase(TestCase):
def __init__(self, methodName):
TestCase.__init__(self, methodName)
self.textParser = None
def isValidText(self, text):
isValid = self.textParser.isValidLine(text)
self.assertEqual(True, isValid)
def isNotValidText(self, text):
isValid = self.textParser.isValidLine(text)
self.assertEqual(False, isValid)

View File

@ -1,19 +1,15 @@
import unittest
from Tests.UnitTests.LineParserTestCaseBase import LineParserTestCaseBase
from parsers.ParserBackup.CreateBackupParser import CreateBackupParser
class TestCreateBackup(unittest.TestCase):
class TestCreateBackup(LineParserTestCaseBase):
def setUp(self):
self.parser = CreateBackupParser()
self.textParser = CreateBackupParser()
def test_isValid(self):
line = "create backup"
isValid = self.parser.isValidLine(line)
self.assertEqual(True, isValid)
self.isValidText('create backup')
self.isValidText('create backup')
def test_isNotValid(self):
line = "create backup bla bla"
isValid = self.parser.isValidLine(line)
self.assertEqual(False, isValid)
self.isNotValidText('create backup ')
self.isNotValidText('create backup bla bla')

View File

@ -1,25 +1,15 @@
import unittest
from Tests.UnitTests.LineParserTestCaseBase import LineParserTestCaseBase
from parsers.ParserBackup.DeleteBackupParser import DeleteBackupParser
class TestDeleteBackup(unittest.TestCase):
class TestDeleteBackup(LineParserTestCaseBase):
def setUp(self):
self.parser = DeleteBackupParser()
self.textParser = DeleteBackupParser()
def test_parseCurrentDir(self):
line = "delete backup '.'"
folderPath = self.parser.parseLine(line)
def test_isValid(self):
self.isValidText('delete backup')
self.isValidText('delete backup')
self.assertEqual('.', folderPath)
def test_parseRelativePath(self):
line = "delete backup '../Some/Path'"
folderPath = self.parser.parseLine(line)
self.assertEqual('../Some/Path', folderPath)
def test_parseAbsPath(self):
line = "delete backup '/Some/Abs/Path'"
folderPath = self.parser.parseLine(line)
self.assertEqual('/Some/Abs/Path', folderPath)
def test_isNotValid(self):
self.isNotValidText('delete backup ')
self.isNotValidText('delete backup bla bla')

View File

@ -1,25 +1,15 @@
import unittest
from Tests.UnitTests.LineParserTestCaseBase import LineParserTestCaseBase
from parsers.ParserBackup.RestoreBackupParser import RestoreBackupParser
class TestRestoreBackup(unittest.TestCase):
class TestRestoreBackup(LineParserTestCaseBase):
def setUp(self):
self.parser = RestoreBackupParser()
self.textParser = RestoreBackupParser()
def test_parseCurrentDir(self):
line = "restore from backup '.'"
folderPath = self.parser.parseLine(line)
def test_isValid(self):
self.isValidText('restore from backup')
self.isValidText('restore from backup')
self.assertEqual('.', folderPath)
def test_parseRelativePath(self):
line = "restore from backup '../Some/Path'"
folderPath = self.parser.parseLine(line)
self.assertEqual('../Some/Path', folderPath)
def test_parseAbsPath(self):
line = "restore from backup '/Some/Abs/Path'"
folderPath = self.parser.parseLine(line)
self.assertEqual('/Some/Abs/Path', folderPath)
def test_isNotValid(self):
self.isNotValidText('restore from backup ')
self.isNotValidText('restore from backup bla bla')

View File

@ -8,11 +8,14 @@ class CreateBackupCommand(BaseBackupCommand):
BaseBackupCommand.__init__(self)
def execute(self):
if os.path.exists(self.backupDirAbsPath):
raise Exception('folder: {0} already exists'.format(self.backupDirAbsPath))
#if os.path.exists(self.backupDirAbsPath):
# raise Exception('folder: {0} already exists'.format(self.backupDirAbsPath))
dirContent = os.listdir(self.srcAbsDirPath)
if os.path.exists(self.backupDirAbsPath):
shutil.rmtree(self.backupDirAbsPath)
os.mkdir(self.backupDirAbsPath)
for fileOrDir in dirContent:

View File

@ -1,21 +1,13 @@
import re
from parsers.LineParser import LineParser
from parsers.InsideParser.InsideParserBase import InsideParserBase
class InsideCsprojSetParser(LineParser):
class InsideCsprojSetParser(InsideParserBase):
def __init__(self, fileExt):
LineParser.__init__(self)
self.__extension = fileExt
InsideParserBase.__init__(self, fileExt)
def parseLine(self, line):
assert line is not None
matchInfo = self.getMatchInfo(line)
match = matchInfo[0]
regexpSource = matchInfo[1]
self._guardMatch(match, line, regexpSource)
match = self.fetchMatchFor(line)
filePath = match.group('file')
key = match.group('key')
@ -27,22 +19,13 @@ class InsideCsprojSetParser(LineParser):
def getMatchInfo(self, line):
assert line is not None
filePathRegexp = r"'(?P<file>[./ a-zA-Z]+\.{0})'".format(self.__extension)
keyRegexp = r'(?P<key>[a-zA-Z]+)'
valueRegexp = r"'(?P<value>[^']+)'"
slnConfigRegexp = r"'(?P<config>[a-zA-Z|]+)'$"
regexpSource = self.startsWith('inside') + filePathRegexp + self.keywordToken('set') + keyRegexp + \
regexpSource = self.startsWith('inside') + self.filePathRegexp + self.keywordToken('set') + keyRegexp + \
self.keywordToken('to') + valueRegexp + self.keywordToken('for') + slnConfigRegexp
regexp = re.compile(regexpSource, re.UNICODE)
match = regexp.match(line)
return match, regexpSource
def isValidLine(self, line):
assert line is not None
matchInfo = self.getMatchInfo(line)
match = matchInfo[0]
return match is not None
return match, regexpSource

View File

@ -0,0 +1,38 @@
import abc
from parsers.LineParser import LineParser
class InsideParserBase(object, LineParser):
__metaclass__ = abc.ABCMeta
def __init__(self, fileExt):
LineParser.__init__(self)
assert fileExt is not None
self.fileExt = fileExt
self.filePathRegexp = r"'(?P<file>[./ a-zA-Z]+\.{0})'".format(self.fileExt)
@abc.abstractmethod
def getMatchInfo(self, line):
"Not implemented"
return None, None
def fetchMatchFor(self, text):
assert text is not None
matchInfo = self.getMatchInfo(text)
match = matchInfo[0]
regexpSource = matchInfo[1]
self._guardMatch(match, text, regexpSource)
return match
def isValidLine(self, line):
assert line is not None
matchInfo = self.getMatchInfo(line)
match = matchInfo[0]
return match is not None

View File

@ -1,35 +1,27 @@
import re
from parsers.LineParser import LineParser
from parsers.InsideParser.InsideParserBase import InsideParserBase
class InsideRemoveParser(LineParser):
class InsideRemoveParser(InsideParserBase):
def __init__(self, fileExt):
LineParser.__init__(self)
assert fileExt is not None
self.__extension = fileExt
InsideParserBase.__init__(self, fileExt)
def parseLine(self, line):
assert line is not None
filePathRegexp = r"'(?P<file>[./ a-zA-Z]+\.{0})'".format(self.__extension)
projectNameRegexp = r'(?P<project>[.a-zA-Z]+)'
regexpSource = self.startsWith('inside') + filePathRegexp + self.keywordToken('remove') + projectNameRegexp + self.spaceEndsWith('project')
regexp = re.compile(regexpSource, re.UNICODE)
match = regexp.match(line)
self._guardMatch(match, line, regexpSource)
match = self.fetchMatchFor(line)
filePath = match.group('file')
projectName = match.group('project')
return filePath, projectName
def isValidLine(self, line):
regexpSrc = r"inside\s+'[./ a-zA-Z]+\.{0}'\s+remove".format(self.__extension)
regexp = re.compile(regexpSrc, re.UNICODE)
def getMatchInfo(self, line):
assert line is not None
filePathRegexp = r"'(?P<file>[./ a-zA-Z]+\.{0})'".format(self.fileExt)
projectNameRegexp = r'(?P<project>[.a-zA-Z]+)'
regexpSource = self.startsWith('inside') + filePathRegexp + self.keywordToken('remove') + projectNameRegexp + self.spaceEndsWith('project')
regexp = re.compile(regexpSource, re.UNICODE)
match = regexp.match(line)
return match is not None
return match, regexpSource

View File

@ -0,0 +1,41 @@
import re
from parsers.InsideParser.InsideParserBase import InsideParserBase
class InsideSetArrayParser(InsideParserBase):
def __init__(self, fileExt):
InsideParserBase.__init__(self, fileExt)
self.values = None
def parseLine(self, line):
match = self.fetchMatchFor(line)
filePath = match.group('file')
key = match.group('key')
valuesStr = match.group('values')
self.values = self.parseValues(valuesStr)
return filePath, key, valuesStr
def getMatchInfo(self, line):
assert line is not None
keyRegexp = r'(?P<key>[a-zA-Z]+)'
valueRegexp = r"'(?P<values>[^']+)'$"
regexpSource = self.startsWith('inside') + self.filePathRegexp + self.keywordToken('set') + keyRegexp + \
self.keywordToken('with') + self.than('values') + valueRegexp
regexp = re.compile(regexpSource, re.UNICODE)
match = regexp.match(line)
return match, regexpSource
def parseValues(self, valuesStr):
assert valuesStr is not None
assert len(valuesStr) > 0
values = valuesStr.split(':')
return values

View File

@ -1,20 +1,13 @@
import re
from parsers.LineParser import LineParser
from parsers.InsideParser.InsideParserBase import InsideParserBase
class InsideSetParser(LineParser):
class InsideSetParser(InsideParserBase):
def __init__(self, fileExt):
LineParser.__init__(self)
self.__extension = fileExt
InsideParserBase.__init__(self, fileExt)
def parseLine(self, line):
assert line is not None
matchInfo = self.getMatchInfo(line)
match = matchInfo[0]
regexpSource = matchInfo[1]
self._guardMatch(match, line, regexpSource)
match = self.fetchMatchFor(line)
filePath = match.group('file')
key = match.group('key')
@ -25,21 +18,13 @@ class InsideSetParser(LineParser):
def getMatchInfo(self, line):
assert line is not None
filePathRegexp = r"'(?P<file>[./ a-zA-Z]+\.{0})'".format(self.__extension)
keyRegexp = r'(?P<key>[a-zA-Z]+)'
valueRegexp = r"'(?P<value>[^']+)'$"
regexpSource = self.startsWith('inside') + filePathRegexp + self.keywordToken('set') + keyRegexp + \
regexpSource = self.startsWith('inside') + self.filePathRegexp + self.keywordToken('set') + keyRegexp + \
self.keywordToken('to') + valueRegexp
regexp = re.compile(regexpSource, re.UNICODE)
match = regexp.match(line)
return match, regexpSource
def isValidLine(self, line):
assert line is not None
matchInfo = self.getMatchInfo(line)
match = matchInfo[0]
return match is not None
return match, regexpSource

View File

@ -12,7 +12,7 @@ print 'current working dir: {0}'.format(baseDirAbsPath)
#import ManualTests.info_plist_test
#import ManualTests.copy_test
#import Tests.ManualTests.create_backup_test
import Tests.ManualTests.delete_backup_test
#import Tests.ManualTests.delete_backup_test
#import Tests.ManualTests.restore_backup_test
#import ManualTests.csproj_test
#import ManualTests.run_sh_command
@ -23,4 +23,6 @@ import Tests.ManualTests.delete_backup_test
#import Tests.ManualTests.testflight_test
#import Tests.ManualTests.install_profile
#import Tests.ManualTests.macros_include_test
#import Tests.ManualTests.resolve_settings
#import Tests.ManualTests.resolve_settings
import Tests.ManualTests.infoPlistMultipleValues_test

View File

@ -9,8 +9,12 @@ class InfoPlistPatcher():
tree = eT.parse(self.__infoPlistPath)
plist_dict = tree.getroot().find('dict')
for key_name in key_value_dict:
self.AppendOrReplaceValueByKey(key_name, key_value_dict[key_name], plist_dict)
for keyName in key_value_dict:
value = key_value_dict[keyName]
if type(value) is str:
self.AppendOrReplaceValueByKey(keyName, value, plist_dict)
else:
self.AppendOrReplaceValuesByKey(keyName, value, plist_dict)
tree.write(self.__infoPlistPath, xml_declaration=True, encoding='UTF-8', method="xml")
@ -23,6 +27,15 @@ class InfoPlistPatcher():
else:
self.AppendKeyValue(key_name, value, dict_element)
def AppendOrReplaceValuesByKey(self, keyName, valuesArr, dictElement):
keyIndex = self.FindIndexByKey(keyName, dictElement)
elementExists = keyIndex >= 0
if elementExists:
self.ReplaceValuesByKeyIndex(keyIndex, valuesArr, dictElement)
else:
self.AppendValues(keyName, valuesArr, dictElement)
def FindIndexByKey(self, key_name, dict_element):
all_keys_elements = dict_element.findall('key')
@ -43,15 +56,50 @@ class InfoPlistPatcher():
value_element = dict_element[value_index]
value_element.text = value
def AppendKeyValue(self, key_name, value, dict_element):
key_element = eT.Element('key')
key_element.text = key_name
def ReplaceValuesByKeyIndex(self, keyIndex, valueArr, dict_element):
valuesIndex = keyIndex + 1
arrayElement = dict_element[valuesIndex]
value_element = eT.Element('string')
value_element.text = value
children = arrayElement.findall('string')
for ch in children:
arrayElement.remove(ch)
self.fillArrayElementWithValues(arrayElement, valueArr)
def AppendKeyValue(self, keyName, value, dict_element):
key_element = self.createKeyElement(keyName)
value_element = self.createValueElement(value)
dict_element.append(key_element)
dict_element.append(value_element)
def AppendValues(self, keyName, valuesArr, parentElement):
keyElement = self.createKeyElement(keyName)
arrayElement = eT.Element('array')
self.fillArrayElementWithValues(arrayElement, valuesArr)
parentElement.append(keyElement)
parentElement.append(arrayElement)
def createKeyElement(self, keyName):
keyElement = eT.Element('key')
keyElement.text = keyName
return keyElement
def createValueElement(self, value):
valueElement = eT.Element('string')
valueElement.text = value
return valueElement
def fillArrayElementWithValues(self, arrayElement, values):
for value in values:
valueElement = self.createValueElement(value)
arrayElement.append(valueElement)

View File

@ -6,6 +6,8 @@ configs = 'appstore, staging'
# ios platform settings
ios.sln_config = 'Release|iPhone'
ios.steps = 'scripts/IosSteps.txt'
ios.setup_steps = 'IosSetupSteps.txt'
ios.tf_api_token = '0e6925075d4fc10fed0e7bbf43fa6894_NjQ0OTI2MjAxMi0wOS0yNSAxMTo0MDozNi40OTY5MjU'
ios.tf_team_token = 'c5c3cf7a6dae2bea4382dfbd181a2075_Mjc4ODkwMjAxMy0wOS0yOSAxNDowOTo1OC40Mzg5MTY'
@ -15,8 +17,8 @@ ios.tf_team_token = 'c5c3cf7a6dae2bea4382dfbd181a2075_Mjc4ODkwMjAxMy0wOS0yOSAxND
# config settings
ios.appstore.app_name = 'CoolApp'
ios.appstore.author = 'Rustam'
ios.appstore.setup_steps = 'IosSetupSteps.txt'
ios.appstore.icons = 'Content/Icons/icon-iphone@2x:Content/Icons/icon-iphone'
ios.staging.app_name = 'CoolApp staging'
ios.staging.steps = 'scripts/StagingSteps.txt'
ios.staging.author = 'Fedor'
ios.staging.author = 'Fedor'
ios.staging.icons = 'Content/Icons/icon-iphone-staging@2x.png:Content/Icons/icon-iphone-staging.png'