Merge branch 'BS-31'
This commit is contained in:
commit
aba01994b3
|
|
@ -0,0 +1,6 @@
|
|||
class BuildConfigProviderBase:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def getConfigs(self, rootConfig):
|
||||
pass
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
class DependencyResolver:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def resolve(self, unresolved):
|
||||
assert unresolved is not None
|
||||
resolved = []
|
||||
|
||||
while len(unresolved) > 0:
|
||||
node = unresolved[0]
|
||||
self.resolveNode(node, resolved, unresolved, [])
|
||||
|
||||
return resolved
|
||||
|
||||
def resolveNode(self, node, resolved, unresolved, seen):
|
||||
assert node is not None
|
||||
assert resolved is not None
|
||||
assert seen is not None
|
||||
|
||||
seen.append(node)
|
||||
|
||||
for dependency in node.edges:
|
||||
if dependency not in resolved:
|
||||
self.guardNotCircularReference(node, dependency, seen)
|
||||
self.resolveNode(dependency, resolved, unresolved, seen)
|
||||
|
||||
resolved.append(node)
|
||||
unresolved.remove(node)
|
||||
seen.remove(node)
|
||||
|
||||
def guardNotCircularReference(self, start, dependency, seen):
|
||||
assert start is not None
|
||||
assert dependency is not None
|
||||
assert seen is not None
|
||||
|
||||
if dependency in seen:
|
||||
raise Exception('Circular reference detected: {0} -> {1}'.format(start.name, dependency.name))
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
class Node:
|
||||
def __init__(self, name):
|
||||
assert name is not None
|
||||
|
||||
self.name = name
|
||||
self.edges = []
|
||||
|
||||
def addEdge(self, node):
|
||||
assert node is not None
|
||||
assert node not in self.edges
|
||||
|
||||
self.edges.append(node)
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from Core.DependencyResolver.DependencyResolver import DependencyResolver
|
||||
from Core.DependencyResolver.Node import Node
|
||||
from Core.LineConveyor.MacroResolver import MacroResolver
|
||||
from commands.ValueProvider import ValueProvider
|
||||
from utils.MacroProcessor import MacroProcessor
|
||||
|
||||
|
||||
class SettingsResolver:
|
||||
def __init__(self, settingsDictionary):
|
||||
assert settingsDictionary is not None
|
||||
|
||||
self.settings = settingsDictionary.copy()
|
||||
self.nodeStorage = {}
|
||||
self.macroProcessor = MacroProcessor()
|
||||
|
||||
self.valueProvider = ValueProvider()
|
||||
self.valueProvider.setConfig(self.settings)
|
||||
|
||||
|
||||
def resolveSettings(self):
|
||||
|
||||
self.fillNodesStorage()
|
||||
unresolved = self.nodeStorage.values()
|
||||
|
||||
dependencyResolver = DependencyResolver()
|
||||
resolved = dependencyResolver.resolve(unresolved)
|
||||
|
||||
self.resolveSettingValues(resolved)
|
||||
return self.settings
|
||||
|
||||
def fillNodesStorage(self):
|
||||
|
||||
for key in self.settings:
|
||||
node = self.fetchNodeByKey(key)
|
||||
|
||||
value = self.settings[key]
|
||||
macroNames = self.macroProcessor.getSymbols(value)
|
||||
|
||||
for symbol in macroNames:
|
||||
name = self.macroProcessor.getNameByMacroName(symbol)
|
||||
dependency = self.fetchNodeByKey(name)
|
||||
|
||||
node.addEdge(dependency)
|
||||
|
||||
def fetchNodeByKey(self, key):
|
||||
assert key is not Node
|
||||
|
||||
node = self.nodeStorage.get(key, Node(key))
|
||||
self.nodeStorage[key] = node
|
||||
|
||||
return node
|
||||
|
||||
def resolveSettingValues(self, resolvedDependencies):
|
||||
macroResolver = MacroResolver(self.macroProcessor, self.valueProvider)
|
||||
|
||||
for node in resolvedDependencies:
|
||||
unresolvedSettingValue = self.settings[node.name]
|
||||
resolvedSettingValue = macroResolver.processText(unresolvedSettingValue)
|
||||
|
||||
self.settings[node.name] = resolvedSettingValue
|
||||
|
|
@ -0,0 +1 @@
|
|||
__author__ = 'rzaitov'
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
from Core.ContentProviderBase import ContentProviderBase
|
||||
from Tests.Common.SettingsProviderStub import SettingsProviderStub
|
||||
from taskRunner import TaskRunner
|
||||
from utils.BuildConfigProvider.BuildConfigProvider import BuildConfigProvider
|
||||
from utils.BuildConfigProvider.ResolvedBuildConfigProvider import ResolvedBuildConfigProvider
|
||||
|
||||
settingsText = """
|
||||
build_tool = '/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool'
|
||||
major_minor = '1.2'
|
||||
build = '345'
|
||||
|
||||
configs = 'config1, config2'
|
||||
steps = 'main_steps'
|
||||
|
||||
config1.version = '{@major_minor}'
|
||||
config2.version = '{@major_minor}.{@build}'
|
||||
"""
|
||||
|
||||
stepsFileContent = """
|
||||
sh echo {@version}
|
||||
"""
|
||||
|
||||
class ContentProviderMock(ContentProviderBase):
|
||||
def __init__(self):
|
||||
ContentProviderBase.__init__(self)
|
||||
|
||||
def fetchContent(self, key):
|
||||
if key == 'main_steps':
|
||||
return stepsFileContent
|
||||
else:
|
||||
raise Exception(key)
|
||||
|
||||
|
||||
settingsProvider = SettingsProviderStub(settingsText)
|
||||
|
||||
buildConfigProvider = BuildConfigProvider()
|
||||
resolvedBuildConfigProvider = ResolvedBuildConfigProvider(buildConfigProvider)
|
||||
|
||||
contentProvider = ContentProviderMock()
|
||||
|
||||
taskRunner = TaskRunner(settingsProvider, contentProvider, resolvedBuildConfigProvider)
|
||||
|
||||
taskRunner.run()
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import unittest
|
||||
from utils.BuildConfigProvider import BuildConfigProvider
|
||||
from utils.BuildConfigProvider.BuildConfigProvider import BuildConfigProvider
|
||||
|
||||
|
||||
class TestBuildConfigProvider(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
__author__ = 'rzaitov'
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import unittest
|
||||
from Core.DependencyResolver.DependencyResolver import DependencyResolver
|
||||
from Core.DependencyResolver.Node import Node
|
||||
|
||||
|
||||
class TestDependencyResolver(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.resolver = DependencyResolver()
|
||||
|
||||
def test_OneConnectedness(self):
|
||||
node1 = Node('node1')
|
||||
node2 = Node('node2')
|
||||
|
||||
node3 = Node('node3')
|
||||
node3.addEdge(node1)
|
||||
node3.addEdge(node2)
|
||||
|
||||
node4 = Node('node4')
|
||||
node4.addEdge(node3)
|
||||
node4.addEdge(node1)
|
||||
|
||||
unresolved = [node4, node3, node2, node1]
|
||||
resolved = self.resolver.resolve(unresolved)
|
||||
|
||||
self.assertEqual(4, len(resolved))
|
||||
|
||||
self.assertEqual(node1, resolved[0])
|
||||
self.assertEqual(node2, resolved[1])
|
||||
self.assertEqual(node3, resolved[2])
|
||||
self.assertEqual(node4, resolved[3])
|
||||
|
||||
def test_TwoConnectedness(self):
|
||||
# first
|
||||
node1 = Node('node1')
|
||||
node2 = Node('node2')
|
||||
|
||||
node3 = Node('node3')
|
||||
node3.addEdge(node1)
|
||||
node3.addEdge(node2)
|
||||
|
||||
node4 = Node('node4')
|
||||
node4.addEdge(node3)
|
||||
node4.addEdge(node1)
|
||||
|
||||
# second
|
||||
node5 = Node('node5')
|
||||
|
||||
node6 = Node('node6')
|
||||
node6.addEdge(node5)
|
||||
|
||||
unresolved = [node4, node3, node2, node1, node6, node5]
|
||||
resolved = self.resolver.resolve(unresolved)
|
||||
|
||||
self.assertEqual(6, len(resolved))
|
||||
|
||||
self.assertEqual(node1, resolved[0])
|
||||
self.assertEqual(node2, resolved[1])
|
||||
self.assertEqual(node3, resolved[2])
|
||||
self.assertEqual(node4, resolved[3])
|
||||
self.assertEqual(node5, resolved[4])
|
||||
self.assertEqual(node6, resolved[5])
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
__author__ = 'rzaitov'
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import unittest
|
||||
from Core.DependencyResolver.SettingsResolver import SettingsResolver
|
||||
|
||||
|
||||
class TestSettingsResolver(unittest.TestCase):
|
||||
def test_resolveSettings(self):
|
||||
unresolvedSettings = {
|
||||
'key1': 'value1',
|
||||
'key2': 'value2',
|
||||
'key3': '{@key1} {@key2}',
|
||||
'key4': '{@key1} {@key3}',
|
||||
|
||||
'key5': 'value5',
|
||||
'key6': '{@key5} value6'
|
||||
}
|
||||
|
||||
settingsResolver = SettingsResolver(unresolvedSettings)
|
||||
resolvedSettings = settingsResolver.resolveSettings()
|
||||
|
||||
self.assertEqual('value1', resolvedSettings['key1'])
|
||||
self.assertEqual('value2', resolvedSettings['key2'])
|
||||
self.assertEqual('value1 value2', resolvedSettings['key3'])
|
||||
self.assertEqual('value1 value1 value2', resolvedSettings['key4'])
|
||||
|
||||
self.assertEqual('value5', resolvedSettings['key5'])
|
||||
self.assertEqual('value5 value6', resolvedSettings['key6'])
|
||||
|
|
@ -20,5 +20,6 @@ os.chdir(baseDir)
|
|||
#import ManualTests.clean_test
|
||||
#import Tests.ManualTests.testflight_test
|
||||
#import Tests.ManualTests.install_profile
|
||||
#import Tests.ManualTests.macros_include_test
|
||||
|
||||
import Tests.ManualTests.macros_include_test
|
||||
import Tests.ManualTests.resolve_settings
|
||||
|
|
@ -8,7 +8,8 @@ from Core.LineConveyor.MacroResolver import MacroResolver
|
|||
from Core.LineConveyor.Stripper import Stripper
|
||||
from Core.LineConveyor.TextInclude import TextInclude
|
||||
from commands.ValueProvider import ValueProvider
|
||||
from utils.BuildConfigProvider import BuildConfigProvider
|
||||
from utils.BuildConfigProvider.BuildConfigProvider import BuildConfigProvider
|
||||
from utils.BuildConfigProvider.ResolvedBuildConfigProvider import ResolvedBuildConfigProvider
|
||||
from utils.IncludeProcessor import IncludeProcessor
|
||||
from utils.MacroProcessor import MacroProcessor
|
||||
from utils.SettingsProvider.CmdArgsOverriderSettingsProvider import CmdArgsOverriderSettingsProvider
|
||||
|
|
@ -23,15 +24,15 @@ from Core.StepsRunner import StepsRunner
|
|||
#os.chdir(baseDir)
|
||||
|
||||
|
||||
|
||||
class TaskRunner:
|
||||
def __init__(self, settingsProvider, fileContentProvider):
|
||||
def __init__(self, settingsProvider, fileContentProvider, buildConfigProvider):
|
||||
assert settingsProvider is not None
|
||||
assert fileContentProvider is not None
|
||||
assert buildConfigProvider is not None
|
||||
|
||||
self.settingsProvider = settingsProvider
|
||||
self.fileContentProvider = fileContentProvider
|
||||
self.configsProvider = BuildConfigProvider()
|
||||
self.configsProvider = buildConfigProvider
|
||||
|
||||
lineStripper = Stripper()
|
||||
commentRemover = CommentRemover()
|
||||
|
|
@ -84,8 +85,12 @@ if __name__ == "__main__":
|
|||
# TODO: перенести в корень комапановки
|
||||
fromFileSettingsProvider = FromFileSettingsProvider()
|
||||
overrideWithCmdSetProvider = CmdArgsOverriderSettingsProvider(fromFileSettingsProvider, overrideArgs)
|
||||
#resolvedSettingsProvider = ResolvedSettingsProvider(CmdArgsOverriderSettingsProvider)
|
||||
|
||||
fContentProvider = FileContentProvider()
|
||||
|
||||
runner = TaskRunner(overrideWithCmdSetProvider, fContentProvider)
|
||||
buildConfigProvider = BuildConfigProvider()
|
||||
resolvedBuildConfigProvider = ResolvedBuildConfigProvider(buildConfigProvider)
|
||||
|
||||
runner = TaskRunner(overrideWithCmdSetProvider, fContentProvider, resolvedBuildConfigProvider)
|
||||
runner.run()
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
class BuildConfigProvider:
|
||||
from Core.BuildConfigProviderBase import BuildConfigProviderBase
|
||||
|
||||
|
||||
class BuildConfigProvider(BuildConfigProviderBase):
|
||||
def __init__(self):
|
||||
pass
|
||||
BuildConfigProviderBase.__init__(self)
|
||||
|
||||
def getConfigs(self, rootConfig):
|
||||
buildReadyConfigNames = self.fetchBuildReadyConfigNames(rootConfig)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
from Core.BuildConfigProviderBase import BuildConfigProviderBase
|
||||
from Core.DependencyResolver.SettingsResolver import SettingsResolver
|
||||
|
||||
|
||||
class ResolvedBuildConfigProvider(BuildConfigProviderBase):
|
||||
def __init__(self, buildConfigProvider):
|
||||
BuildConfigProviderBase.__init__(self)
|
||||
assert buildConfigProvider is not None
|
||||
|
||||
self.inner = buildConfigProvider
|
||||
|
||||
def getConfigs(self, rootConfig):
|
||||
unresolvedBuildConfigs = self.inner.getConfigs(rootConfig)
|
||||
resolvedBuildConfigs = []
|
||||
|
||||
for bc in unresolvedBuildConfigs:
|
||||
resolver = SettingsResolver(bc)
|
||||
resolvedBuildConfig = resolver.resolveSettings()
|
||||
|
||||
resolvedBuildConfigs.append(resolvedBuildConfig)
|
||||
|
||||
return resolvedBuildConfigs
|
||||
|
|
@ -0,0 +1 @@
|
|||
__author__ = 'rzaitov'
|
||||
|
|
@ -16,6 +16,11 @@ class MacroProcessor:
|
|||
|
||||
return macro[1:-1]
|
||||
|
||||
def getNameByMacroName(self, macroName):
|
||||
assert macroName.startswith('@')
|
||||
|
||||
return macroName[1:]
|
||||
|
||||
def getSymbols(self, line):
|
||||
assert line is not None
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue