diff --git a/scripts/Core/LineConveyor/CommentRemover.py b/scripts/Core/LineConveyor/CommentRemover.py new file mode 100644 index 0000000..4567066 --- /dev/null +++ b/scripts/Core/LineConveyor/CommentRemover.py @@ -0,0 +1,10 @@ +class CommentRemover: + def processLine(self, line): + assert line is not None + + newLine = line + index = line.find('#') + if index >= 0: + newLine = line[:index] + + return newLine \ No newline at end of file diff --git a/scripts/Core/LineConveyor/LineConveyor.py b/scripts/Core/LineConveyor/LineConveyor.py new file mode 100644 index 0000000..3231185 --- /dev/null +++ b/scripts/Core/LineConveyor/LineConveyor.py @@ -0,0 +1,16 @@ +class LineConveyor: + def __init__(self): + self.processors = [] + + def addProcessor(self, processor): + assert processor is not None + + self.processors.append(processor) + + def processLine(self, line): + assert line is not None + + for processor in self.processors: + line = processor.processLine(line) + + return line diff --git a/scripts/Core/LineConveyor/MacroResolver.py b/scripts/Core/LineConveyor/MacroResolver.py new file mode 100644 index 0000000..a57b5fe --- /dev/null +++ b/scripts/Core/LineConveyor/MacroResolver.py @@ -0,0 +1,20 @@ +class MacroResolver: + def __init__(self, macroProcessor, valueProvider): + assert macroProcessor is not None + assert valueProvider is not None + + self.macroProcessor = macroProcessor + self.valueProvider = valueProvider + + def processLine(self, line): + assert line is not None + + symbols = self.macroProcessor.getSymbols(line) + + for sym in symbols: + macro = self.macroProcessor.getMacroByName(sym) + value = self.valueProvider.getValueFor(sym) + + line = line.replace(macro, value) + + return line \ No newline at end of file diff --git a/scripts/Core/LineConveyor/Stripper.py b/scripts/Core/LineConveyor/Stripper.py new file mode 100644 index 0000000..9b57bee --- /dev/null +++ b/scripts/Core/LineConveyor/Stripper.py @@ -0,0 +1,5 @@ +class Stripper: + def processLine(self, line): + assert line is not None + + return line.strip(' \t\n\r') diff --git a/scripts/StepRunner/__init__.py b/scripts/Core/LineConveyor/__init__.py similarity index 100% rename from scripts/StepRunner/__init__.py rename to scripts/Core/LineConveyor/__init__.py diff --git a/scripts/StepRunner/StepsRunner.py b/scripts/Core/StepsRunner.py similarity index 89% rename from scripts/StepRunner/StepsRunner.py rename to scripts/Core/StepsRunner.py index b805fc7..51e1d01 100644 --- a/scripts/StepRunner/StepsRunner.py +++ b/scripts/Core/StepsRunner.py @@ -8,14 +8,16 @@ from CommandBuilders.PatchInfoplistCommandBuilder import PatchInfoplistCommandBu from CommandBuilders.RemoveProjectCommandBuilder import RemoveProjectCommandBuilder from CommandBuilders.RestoreBackupCommandBuilder import RestoreBackupCommandBuilder from CommandBuilders.ShCommandBuilder import ShCommandBuilder -from commands.ValueProvider import ValueProvider class StepsRunner: - def __init__(self, config): + def __init__(self, config, compositeLineProcessor, valueProvider): assert config is not None + assert compositeLineProcessor is not None + assert valueProvider is not None - self.valueProvider = ValueProvider(config) + self.lineConveyor = compositeLineProcessor + self.valueProvider = valueProvider self.shCommandBuilder = ShCommandBuilder() self.removeProjectBuilder = RemoveProjectCommandBuilder() @@ -36,14 +38,12 @@ class StepsRunner: lines = content.splitlines() for line in lines: - stripped = line.strip(' \t\n\r') + processedLine = self.lineConveyor.processLine(line) - if len(stripped) == 0: - continue - if stripped.startswith("#"): + if len(processedLine) == 0: continue else: - self.processLine(stripped) + self.processLine(processedLine) def processLine(self, line): if self.shCommandBuilder.isShCommand(line): diff --git a/scripts/Core/__init__.py b/scripts/Core/__init__.py new file mode 100644 index 0000000..cc31abc --- /dev/null +++ b/scripts/Core/__init__.py @@ -0,0 +1 @@ +__author__ = 'rzaitov' diff --git a/scripts/IosSteps.txt b/scripts/IosSteps.txt index 870290c..8ef53bc 100644 --- a/scripts/IosSteps.txt +++ b/scripts/IosSteps.txt @@ -1,22 +1,22 @@ +sh echo hello from '{@author}' + restore from backup create backup for 'BuildSample' inside 'BuildSample/BuildSample.sln' remove NotCompileApp project inside 'BuildSample/BuildSample/CoolApp.csproj' set OutputPath to 'Output' -inside 'BuildSample/BuildSample/Info.plist' set CFBundleVersion to '1.2.3' +inside 'BuildSample/BuildSample/Info.plist' set CFBundleVersion to '{@version}' inside 'BuildSample/BuildSample/Info.plist' set CFBundleDisplayName to 'CoolApp' copy 'BuildSample/BuildSample/Profiles/8F606DAE-F9C9-4A19-8EFF-34B990D76C28.mobileprovision' to '~/Library/MobileDevice/Provisioning Profiles/BuildScript.mobileprovision' -clean 'BuildSample/BuildSample.sln' for 'Release|iPhone' -build 'BuildSample/BuildSample.sln' for 'Release|iPhone' +clean 'BuildSample/BuildSample.sln' for '{@sln_config}' +build 'BuildSample/BuildSample.sln' for '{@sln_config}' create dirs 'Output/Appstore/Artifacts' -copy 'BuildSample/BuildSample/Output/BuildSample-1.2.3.ipa' to 'Output/Appstore/Artifacts' +copy 'BuildSample/BuildSample/Output/BuildSample-{@version}.ipa' to 'Output/Appstore/Artifacts' sh cp -a BuildSample/BuildSample/Output/ Output/Appstore/ restore from backup -delete backup - -sh echo hello from Rustam \ No newline at end of file +delete backup \ No newline at end of file diff --git a/scripts/Tests/UnitTests/LineConveyor/__init__.py b/scripts/Tests/UnitTests/LineConveyor/__init__.py new file mode 100644 index 0000000..cc31abc --- /dev/null +++ b/scripts/Tests/UnitTests/LineConveyor/__init__.py @@ -0,0 +1 @@ +__author__ = 'rzaitov' diff --git a/scripts/Tests/UnitTests/LineConveyor/test_commentRemover.py b/scripts/Tests/UnitTests/LineConveyor/test_commentRemover.py new file mode 100644 index 0000000..5c0baf8 --- /dev/null +++ b/scripts/Tests/UnitTests/LineConveyor/test_commentRemover.py @@ -0,0 +1,19 @@ +import unittest +from Core.LineConveyor.CommentRemover import CommentRemover + + +class TestCommentRemover(unittest.TestCase): + def setUp(self): + self.commentRemover = CommentRemover() + + def test_startsWithComment(self): + line = '# this line is comment' + newLine = self.commentRemover.processLine(line) + + self.assertEqual('', newLine) + + def test_containsComment(self): + line = 'this line contains # a comment' + newLine = self.commentRemover.processLine(line) + + self.assertEqual('this line contains ', newLine) \ No newline at end of file diff --git a/scripts/Tests/UnitTests/LineConveyor/test_macroResolver.py b/scripts/Tests/UnitTests/LineConveyor/test_macroResolver.py new file mode 100644 index 0000000..019b5a1 --- /dev/null +++ b/scripts/Tests/UnitTests/LineConveyor/test_macroResolver.py @@ -0,0 +1,23 @@ +import unittest +from Core.LineConveyor.MacroResolver import MacroResolver +from commands.ValueProvider import ValueProvider +from utils.MacroProcessor import MacroProcessor + + +class TestMacroResolver(unittest.TestCase): + def setUp(self): + config = { + 'key1': 'hello world', + 'some_name': 'another name', + 'version': '1.2.3' + } + + macroProcessor = MacroProcessor() + valueProvider = ValueProvider(config) + self.macroResolver = MacroResolver(macroProcessor, valueProvider) + + def test_resolveLine(self): + line = '{@key1} bla {@some_name} version: {@version}' + newLine = self.macroResolver.processLine(line) + + self.assertEqual('hello world bla another name version: 1.2.3', newLine) \ No newline at end of file diff --git a/scripts/Tests/UnitTests/LineConveyor/test_stripper.py b/scripts/Tests/UnitTests/LineConveyor/test_stripper.py new file mode 100644 index 0000000..75057be --- /dev/null +++ b/scripts/Tests/UnitTests/LineConveyor/test_stripper.py @@ -0,0 +1,13 @@ +import unittest +from Core.LineConveyor.Stripper import Stripper + + +class TestStripper(unittest.TestCase): + def setUp(self): + self.stripper = Stripper() + + def test_stripLine(self): + line = ' \tSome text \t\r\n' + newLine = self.stripper.processLine(line) + + self.assertEqual('Some text', newLine) \ No newline at end of file diff --git a/scripts/Tests/UnitTests/Macro/__init__.py b/scripts/Tests/UnitTests/Macro/__init__.py new file mode 100644 index 0000000..cc31abc --- /dev/null +++ b/scripts/Tests/UnitTests/Macro/__init__.py @@ -0,0 +1 @@ +__author__ = 'rzaitov' diff --git a/scripts/Tests/UnitTests/Macro/test_macro.py b/scripts/Tests/UnitTests/Macro/test_macro.py new file mode 100644 index 0000000..dc89ac4 --- /dev/null +++ b/scripts/Tests/UnitTests/Macro/test_macro.py @@ -0,0 +1,28 @@ +import unittest +from utils.MacroProcessor import MacroProcessor + + +class TestMacro(unittest.TestCase): + def setUp(self): + self.macroParser = MacroProcessor() + + def test_parseMacros(self): + line = 'hello {@this} is {@my_macro} and {@macro_with_numbers123}' + symbols = self.macroParser.getSymbols(line) + + self.assertEqual(3, len(symbols)) + self.assertTrue('this' in symbols) + self.assertTrue('my_macro' in symbols) + self.assertTrue('macro_with_numbers123' in symbols) + + def test_getName(self): + line = '{@macro_name}' + name = self.macroParser.getMacroName(line) + + self.assertEqual('@macro_name', name) + + def test_getMacro(self): + line = '@some_name' + macro = self.macroParser.getMacroByName(line) + + self.assertEqual('{@some_name}', macro) \ No newline at end of file diff --git a/scripts/commands/ValueProvider.py b/scripts/commands/ValueProvider.py index 8423cb9..bd5fea1 100644 --- a/scripts/commands/ValueProvider.py +++ b/scripts/commands/ValueProvider.py @@ -1,7 +1,6 @@ class ValueProvider: - def __init__(self, config): + def setConfig(self, config): assert config is not None - self.__config = config def getValueFor(self, link): diff --git a/scripts/settings.txt b/scripts/settings.txt index ae50dd1..8b5a24c 100644 --- a/scripts/settings.txt +++ b/scripts/settings.txt @@ -12,6 +12,8 @@ ios.steps = 'scripts/IosSteps.txt' ios.appstore.build_ready = 'true' ios.appstore.app_name = 'CoolApp' ios.appstore.sln_config = 'Release|iPhone' +ios.appstore.author = 'Rustam' +ios.appstore.version = '7.7.7' #ios.staging.build_ready = 'true' ios.staging.app_name = 'CoolApp staging' diff --git a/scripts/taskRunner.py b/scripts/taskRunner.py index f9f73a3..a58f578 100644 --- a/scripts/taskRunner.py +++ b/scripts/taskRunner.py @@ -1,6 +1,12 @@ import os +from Core.LineConveyor.CommentRemover import CommentRemover +from Core.LineConveyor.LineConveyor import LineConveyor +from Core.LineConveyor.MacroResolver import MacroResolver +from Core.LineConveyor.Stripper import Stripper +from commands.ValueProvider import ValueProvider from utils.BuildConfigProvider import BuildConfigProvider from utils.FromFileSettingsProvider import FromFileSettingsProvider +from utils.MacroProcessor import MacroProcessor scriptFilePath = os.path.abspath(__file__) @@ -9,27 +15,38 @@ baseDir = os.path.join(scriptDir, os.pardir) os.chdir(baseDir) -from StepRunner.StepsRunner import StepsRunner +from Core.StepsRunner import StepsRunner class TaskRunner: def __init__(self): - pass + self.configsProvider = BuildConfigProvider() + self.settingsProvider = FromFileSettingsProvider() + + lineStripper = Stripper() + commentRemover = CommentRemover() + + macroProcessor = MacroProcessor() + self.valueProvider = ValueProvider() + macroResolver = MacroResolver(macroProcessor, self.valueProvider) + + self.lineConveyor = LineConveyor() + self.lineConveyor.addProcessor(lineStripper) + self.lineConveyor.addProcessor(commentRemover) + self.lineConveyor.addProcessor(macroResolver) def run(self): - settingsProvider = FromFileSettingsProvider() - settings = settingsProvider.fetchSettings() - - configsProvider = BuildConfigProvider() - buildReadyConfigs = configsProvider.getConfigs(settings) + settings = self.settingsProvider.fetchSettings() + buildReadyConfigs = self.configsProvider.getConfigs(settings) for bc in buildReadyConfigs: + self.valueProvider.setConfig(bc) self.runConfig(bc) def runConfig(self, config): content = self.getStepsContent(config) - stepsRunner = StepsRunner(config) + stepsRunner = StepsRunner(config, self.lineConveyor, self.valueProvider) stepsRunner.run(content) def getStepsContent(self, config): diff --git a/scripts/utils/MacroProcessor.py b/scripts/utils/MacroProcessor.py new file mode 100644 index 0000000..911647d --- /dev/null +++ b/scripts/utils/MacroProcessor.py @@ -0,0 +1,31 @@ +import re + +class MacroProcessor: + def __init__(self): + pass + + def getMacroByName(self, macroName): + assert macroName is not None + assert macroName.startswith('@') + + return '{' + macroName + '}' + + def getMacroName(self, macro): + assert macro.startswith('{@') + assert macro.endswith('}') + + return macro[1:-1] + + def getSymbols(self, line): + assert line is not None + + symRegexp = r"{(?P@[\w]+)}" + regexp = re.compile(symRegexp) + + result = regexp.findall(line) + symbols = [] + if result is not None: + for r in result: + symbols.append(r) + + return symbols \ No newline at end of file