Merge branch 'BS-31'

This commit is contained in:
rzaitov 2013-11-11 18:20:13 +04:00
commit aba01994b3
17 changed files with 298 additions and 9 deletions

View File

@ -0,0 +1,6 @@
class BuildConfigProviderBase:
def __init__(self):
pass
def getConfigs(self, rootConfig):
pass

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

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

View File

@ -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()

View File

@ -1,5 +1,5 @@
import unittest
from utils.BuildConfigProvider import BuildConfigProvider
from utils.BuildConfigProvider.BuildConfigProvider import BuildConfigProvider
class TestBuildConfigProvider(unittest.TestCase):

View File

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

View File

@ -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])

View File

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

View File

@ -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'])

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

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

View File

@ -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