summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--manifest_xml.py55
-rw-r--r--subcmds/manifest.py30
2 files changed, 78 insertions, 7 deletions
diff --git a/manifest_xml.py b/manifest_xml.py
index bf730caa..e1ef330f 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -283,9 +283,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
283 def _ParseGroups(self, groups): 283 def _ParseGroups(self, groups):
284 return [x for x in re.split(r'[,\s]+', groups) if x] 284 return [x for x in re.split(r'[,\s]+', groups) if x]
285 285
286 def Save(self, fd, peg_rev=False, peg_rev_upstream=True, peg_rev_dest_branch=True, groups=None): 286 def ToXml(self, peg_rev=False, peg_rev_upstream=True, peg_rev_dest_branch=True, groups=None):
287 """Write the current manifest out to the given file descriptor. 287 """Return the current manifest XML."""
288 """
289 mp = self.manifestProject 288 mp = self.manifestProject
290 289
291 if groups is None: 290 if groups is None:
@@ -459,6 +458,56 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
459 ' '.join(self._repo_hooks_project.enabled_repo_hooks)) 458 ' '.join(self._repo_hooks_project.enabled_repo_hooks))
460 root.appendChild(e) 459 root.appendChild(e)
461 460
461 return doc
462
463 def ToDict(self, **kwargs):
464 """Return the current manifest as a dictionary."""
465 # Elements that may only appear once.
466 SINGLE_ELEMENTS = {
467 'notice',
468 'default',
469 'manifest-server',
470 'repo-hooks',
471 }
472 # Elements that may be repeated.
473 MULTI_ELEMENTS = {
474 'remote',
475 'remove-project',
476 'project',
477 'extend-project',
478 'include',
479 # These are children of 'project' nodes.
480 'annotation',
481 'project',
482 'copyfile',
483 'linkfile',
484 }
485
486 doc = self.ToXml(**kwargs)
487 ret = {}
488
489 def append_children(ret, node):
490 for child in node.childNodes:
491 if child.nodeType == xml.dom.Node.ELEMENT_NODE:
492 attrs = child.attributes
493 element = dict((attrs.item(i).localName, attrs.item(i).value)
494 for i in range(attrs.length))
495 if child.nodeName in SINGLE_ELEMENTS:
496 ret[child.nodeName] = element
497 elif child.nodeName in MULTI_ELEMENTS:
498 ret.setdefault(child.nodeName, []).append(element)
499 else:
500 raise ManifestParseError('Unhandled element "%s"' % (child.nodeName,))
501
502 append_children(element, child)
503
504 append_children(ret, doc.firstChild)
505
506 return ret
507
508 def Save(self, fd, **kwargs):
509 """Write the current manifest out to the given file descriptor."""
510 doc = self.ToXml(**kwargs)
462 doc.writexml(fd, '', ' ', '\n', 'UTF-8') 511 doc.writexml(fd, '', ' ', '\n', 'UTF-8')
463 512
464 def _output_manifest_project_extras(self, p, e): 513 def _output_manifest_project_extras(self, p, e):
diff --git a/subcmds/manifest.py b/subcmds/manifest.py
index f0a0d069..0052d7aa 100644
--- a/subcmds/manifest.py
+++ b/subcmds/manifest.py
@@ -15,6 +15,8 @@
15# limitations under the License. 15# limitations under the License.
16 16
17from __future__ import print_function 17from __future__ import print_function
18
19import json
18import os 20import os
19import sys 21import sys
20 22
@@ -68,6 +70,10 @@ to indicate the remote ref to push changes to via 'repo upload'.
68 help='If in -r mode, do not write the dest-branch field. ' 70 help='If in -r mode, do not write the dest-branch field. '
69 'Only of use if the branch names for a sha1 manifest are ' 71 'Only of use if the branch names for a sha1 manifest are '
70 'sensitive.') 72 'sensitive.')
73 p.add_option('--json', default=False, action='store_true',
74 help='Output manifest in JSON format (experimental).')
75 p.add_option('--pretty', default=False, action='store_true',
76 help='Format output for humans to read.')
71 p.add_option('-o', '--output-file', 77 p.add_option('-o', '--output-file',
72 dest='output_file', 78 dest='output_file',
73 default='-', 79 default='-',
@@ -83,10 +89,26 @@ to indicate the remote ref to push changes to via 'repo upload'.
83 fd = sys.stdout 89 fd = sys.stdout
84 else: 90 else:
85 fd = open(opt.output_file, 'w') 91 fd = open(opt.output_file, 'w')
86 self.manifest.Save(fd, 92 if opt.json:
87 peg_rev=opt.peg_rev, 93 print('warning: --json is experimental!', file=sys.stderr)
88 peg_rev_upstream=opt.peg_rev_upstream, 94 doc = self.manifest.ToDict(peg_rev=opt.peg_rev,
89 peg_rev_dest_branch=opt.peg_rev_dest_branch) 95 peg_rev_upstream=opt.peg_rev_upstream,
96 peg_rev_dest_branch=opt.peg_rev_dest_branch)
97
98 json_settings = {
99 # JSON style guide says Uunicode characters are fully allowed.
100 'ensure_ascii': False,
101 # We use 2 space indent to match JSON style guide.
102 'indent': 2 if opt.pretty else None,
103 'separators': (',', ': ') if opt.pretty else (',', ':'),
104 'sort_keys': True,
105 }
106 fd.write(json.dumps(doc, **json_settings))
107 else:
108 self.manifest.Save(fd,
109 peg_rev=opt.peg_rev,
110 peg_rev_upstream=opt.peg_rev_upstream,
111 peg_rev_dest_branch=opt.peg_rev_dest_branch)
90 fd.close() 112 fd.close()
91 if opt.output_file != '-': 113 if opt.output_file != '-':
92 print('Saved manifest to %s' % opt.output_file, file=sys.stderr) 114 print('Saved manifest to %s' % opt.output_file, file=sys.stderr)