From ee49ac0ec514ecc6f54e9d06a33f534c1b85b14d Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Fri, 24 Sep 2010 08:27:50 -0700 Subject: [PATCH] loman: Add support for adding elements from default.xml This is needed in order to do the right thing when adding projects which require a revision attribute. BUG=6811 TEST=Updated unittests and verified they pass. Verified that I can add chromeos-kernel-next and revision gets set. Change-Id: I12818dad464094cd50098170da3fcf38b1e32f17 Review URL: http://codereview.chromium.org/3400019 --- bin/loman.py | 94 ++++++++++++++++++++++++++++++------------- bin/loman_unittest.py | 77 ++++++++++++++++++++++++++++++----- 2 files changed, 135 insertions(+), 36 deletions(-) diff --git a/bin/loman.py b/bin/loman.py index ddb6d6d621..0ae74e685e 100755 --- a/bin/loman.py +++ b/bin/loman.py @@ -24,6 +24,17 @@ def _FindRepoDir(): return None +def _ReadManifest(manifest, err_not_found=False): + if os.path.isfile(manifest): + ptree = LocalManifest(open(manifest).read()) + elif err_not_found: + Die('Manifest file, %s, not found' % manifest) + else: + ptree = LocalManifest() + ptree.Parse() + return ptree + + class LocalManifest: """Class which provides an abstraction for manipulating the local manifest.""" @@ -34,63 +45,92 @@ class LocalManifest: """Parse the manifest.""" self._root = ElementTree.fromstring(self._text) - def AddWorkonProject(self, name, path): - """Add a new workon project if it is not already in the manifest. + def AddProjectElement(self, element, workon='False'): + """Add a new project element to the manifest tree. Returns: True on success. """ - + name = element.attrib['name'] + path = element.attrib['path'] for project in self._root.findall('project'): if project.attrib['path'] == path or project.attrib['name'] == name: if project.attrib['path'] == path and project.attrib['name'] == name: return True else: return False - self._AddProject(name, path, workon='True') - return True - - def _AddProject(self, name, path, workon='False'): - element = ElementTree.Element('project', name=name, path=path, - workon=workon) + element.attrib['workon'] = workon element.tail = '\n' self._root.append(element) + return True + + def AddProject(self, name, path, workon='False'): + """Add a workon project if it is not already in the manifest. + + Returns: + True on success. + """ + element = ElementTree.Element('project', name=name, path=path) + return self.AddProjectElement(element, workon=workon) + + def AddWorkonProjectElement(self, element): + return self.AddProjectElement(element, workon='True') + + def AddWorkonProject(self, name, path): + return self.AddProject(name, path, workon='True') + + def GetProject(self, name): + """Accessor method for getting a project node from the manifest tree. + + Returns: + project element node from ElementTree, otherwise, None + """ + + for project in self._root.findall('project'): + if project.attrib['name'] == name: + return project + return None def ToString(self): return ElementTree.tostring(self._root, encoding='UTF-8') def main(argv): - usage = 'usage: %prog add [options] ' + repo_dir = _FindRepoDir() + if not repo_dir: + Die("Unable to find repo dir.") + + usage = 'usage: %prog add [options] ' parser = optparse.OptionParser(usage=usage) parser.add_option('-w', '--workon', action='store_true', dest='workon', default=False, help='Is this a workon package?') - parser.add_option('-f', '--file', dest='manifest', + parser.add_option('-f', '--file', dest='local_manifest', + default='%s/local_manifest.xml' % repo_dir, help='Non-default manifest file to read.') + parser.add_option('-d', '--default', dest='full_manifest', + default='%s/manifests/full.xml' % repo_dir, + help='Default manifest file to read.') (options, args) = parser.parse_args(argv[2:]) - if len(args) < 2: + if len(args) < 1: parser.error('Not enough arguments') if argv[1] not in ['add']: parser.error('Unsupported command: %s.' % argv[1]) if not options.workon: parser.error('Adding of non-workon projects is currently unsupported.') - (name, path) = (args[0], args[1]) + name = args[0] + + local_tree = _ReadManifest(options.local_manifest) + full_tree = _ReadManifest(options.full_manifest) + + project_element = full_tree.GetProject(name) + if project_element == None: + Die('No project named, %s, in the default manifest.' % name) + success = local_tree.AddWorkonProjectElement(project_element) + if not success: + Die('name "%s" already exits with a different path.' % name) - repo_dir = _FindRepoDir() - if not repo_dir: - Die("Unable to find repo dir.") - local_manifest = options.manifest or \ - os.path.join(_FindRepoDir(), 'local_manifest.xml') - if os.path.isfile(local_manifest): - ptree = LocalManifest(open(local_manifest).read()) - else: - ptree = LocalManifest() - ptree.Parse() - if not ptree.AddWorkonProject(name, path): - Die('Path "%s" or name "%s" already exits in the manifest.' % - (path, name)) try: - print >> open(local_manifest, 'w'), ptree.ToString() + print >> open(options.local_manifest, 'w'), local_tree.ToString() except Exception, e: Die('Error writing to manifest: %s' % e) diff --git a/bin/loman_unittest.py b/bin/loman_unittest.py index 4782ac32b5..5788f0378a 100755 --- a/bin/loman_unittest.py +++ b/bin/loman_unittest.py @@ -38,6 +38,13 @@ class LocalManifestTest(unittest.TestCase): ptree.Parse() self.assertEqual(ptree.ToString(), self.utf8 + self.tiny_manifest) + def testGetProject(self): + ptree = loman.LocalManifest('\n') + ptree.Parse() + ptree.AddProject('foo', 'path/to/foo') + project = ptree.GetProject('foo') + self.assertEqual(project.attrib['name'], 'foo') + def testAddNew(self): ptree = loman.LocalManifest('\n') ptree.Parse() @@ -48,6 +55,19 @@ class LocalManifestTest(unittest.TestCase): '\n' '') + def testAddNewElement(self): + dtree = loman.LocalManifest('\n') + dtree.Parse() + dtree.AddProject('foo', 'path/to/foo') + ptree = loman.LocalManifest('\n') + ptree.Parse() + ptree.AddWorkonProjectElement(dtree.GetProject('foo')) + self.assertEqual( + ptree.ToString(), + self.utf8 + '\n' + '\n' + '') + def testAddDup(self): ptree = loman.LocalManifest('\n') ptree.Parse() @@ -83,30 +103,69 @@ class MainTest(unittest.TestCase): self.assertTrue(sys.stderr.getvalue().endswith(err_msg)) def testSimpleAdd(self): + default = tempfile.NamedTemporaryFile('w') + print >> default, '\n' \ + '\n' \ + '\n' + default.flush() + os.fsync(default.fileno()) temp = tempfile.NamedTemporaryFile('w') print >> temp, '\n' temp.flush() os.fsync(temp.fileno()) - loman.main(['loman', 'add', '--workon', '-f', - temp.name, 'foo', 'path/to/foo']) + loman.main(['loman', 'add', '--workon', '-f', temp.name, + '-d', default.name, 'foo']) self.assertEqual( open(temp.name, 'r').read(), self.utf8 + '\n' '\n' '\n') - def testAddDup(self): + def testIgnoredPath(self): + default = tempfile.NamedTemporaryFile('w') + print >> default, '\n' \ + '\n' \ + '\n' + default.flush() + os.fsync(default.fileno()) temp = tempfile.NamedTemporaryFile('w') print >> temp, '\n' temp.flush() os.fsync(temp.fileno()) - loman.main(['loman', 'add', '--workon', '-f', - temp.name, 'foo', 'path/to/foo']) - loman.main(['loman', 'add', '--workon', '-f', - temp.name, 'foo', 'path/to/foo']) + loman.main(['loman', 'add', '--workon', '-f', temp.name, + '-d', default.name, 'foo']) + + def testAddDup(self): + default = tempfile.NamedTemporaryFile('w') + print >> default, '\n' \ + '\n' \ + '\n' + default.flush() + os.fsync(default.fileno()) + temp = tempfile.NamedTemporaryFile('w') + print >> temp, '\n' \ + '\n' \ + '\n' + temp.flush() + os.fsync(temp.fileno()) self.assertRaises(SystemExit, loman.main, - ['loman', 'add', '--workon', '-f', - temp.name, 'foo', 'path/foo']) + ['loman', 'add', '--workon', '-f', temp.name, + '-d', default.name, 'foo']) + + def testAddNonexistant(self): + default = tempfile.NamedTemporaryFile('w') + print >> default, '\n' \ + '\n' \ + '\n' + default.flush() + os.fsync(default.fileno()) + temp = tempfile.NamedTemporaryFile('w') + print >> temp, '\n' + temp.flush() + os.fsync(temp.fileno()) + self.assertRaises(SystemExit, loman.main, + ['loman', 'add', '--workon', '-f', temp.name, + '-d', default.name, 'bar']) if __name__ == '__main__':