~beuno/bzr-xmloutput/xml-beuno

1 by Guillermo Gonzalez
* intial import
1
#!/usr/bin/env python2.4
2
4 by Guillermo Gonzalez
Fix some lines lenght and typos
3
# @author Guillermo Gonzalez
4
# @version 0.1
5
"""
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
6
This plugin provides xml output for three commands (status, log, annotate)
7
adding a --xml option to each
1 by Guillermo Gonzalez
* intial import
8
4 by Guillermo Gonzalez
Fix some lines lenght and typos
9
(most of this is code was modified from bzrlib.cmd_status, 
10
bzrlib.status, bzrlib.delta.TreeDelta.show and bzrlib.log.LongLogFormatter)
11
"""
7 by Guillermo Gonzalez
* Fixed annotation --xml, now always is executed with --all and --long
12
from bzrlib.commands import display_command, register_command
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
13
from bzrlib import builtins
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
14
from bzrlib.log import LogFormatter, log_formatter_registry, LogRevision
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
15
from bzrlib.option import Option
16
from bzrlib.workingtree import WorkingTree
17
import sys
18
19
class cmd_status(builtins.cmd_status):
7 by Guillermo Gonzalez
* Fixed annotation --xml, now always is executed with --all and --long
20
    builtins.cmd_status.takes_options.append(Option('xml', help='show status in xml format'))
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
21
    __doc__ = builtins.cmd_status.__doc__
22
    @display_command
23
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
24
            versioned=False, xml=False):
25
        if xml:
26
            from statusxml import show_tree_status_xml
27
            tree, file_list = builtins.tree_files(file_list)
28
            show_tree_status_xml(tree, show_ids=show_ids,
29
                    specific_files=file_list, revision=revision,
30
                    to_file=self.outf, versioned=False)
31
        else:
32
            status_class.run(self, show_ids=show_ids, file_list=file_list, 
33
                    revision=revision, short=short, versioned=versioned)
34
35
class cmd_annotate(builtins.cmd_annotate):
7 by Guillermo Gonzalez
* Fixed annotation --xml, now always is executed with --all and --long
36
    builtins.cmd_annotate.takes_options.append(Option('xml', help='show annotations in xml format'))
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
37
    __doc__ = builtins.cmd_annotate.__doc__
38
39
    @display_command
40
    def run(self, filename, all=False, long=False, revision=None,
41
            show_ids=False, xml=False):
42
        if xml:
43
            from annotatexml import annotate_file_xml
44
            tree, relpath = WorkingTree.open_containing(filename)
45
            wt_root_path = tree.id2abspath(tree.get_root_id())
46
            branch = tree.branch
47
            branch.lock_read()
48
            try:
49
                if revision is None:
50
                    revision_id = branch.last_revision()
51
                elif len(revision) != 1:
52
                    raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
53
                else:
54
                    revision_id = revision[0].in_history(branch).rev_id
55
                file_id = tree.path2id(relpath)
56
                tree = branch.repository.revision_tree(revision_id)
57
                file_version = tree.inventory[file_id].revision
58
                # always run with --all and --long option (to get the author of each line)
59
                annotate_file_xml(branch=branch, rev_id=file_version, 
8 by Guillermo Gonzalez
* fix keyword argument in annotate_file_xml
60
                        file_id=file_id, to_file=sys.stdout,
9 by Guillermo Gonzalez
* Added file attribute to annotation, which contain the path to the file annotated
61
                        show_ids=show_ids, wt_root_path=wt_root_path, file_path=relpath)
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
62
            finally:
63
                branch.unlock()
64
        else:
65
            annotate_class.run(self, filename=filename, all=all, long=long, revision=revision,
66
            show_ids=show_ids)
67
9 by Guillermo Gonzalez
* Added file attribute to annotation, which contain the path to the file annotated
68
class cmd_log(builtins.cmd_log):
69
    __doc__ = builtins.cmd_log.__doc__
70
    
71
    @display_command
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
72
    def run(self, location=None, timezone='original',
73
            verbose=False,
74
            show_ids=False,
75
            forward=False,
76
            revision=None,
77
            log_format=None,
78
            message=None,
79
            limit=None):
9 by Guillermo Gonzalez
* Added file attribute to annotation, which contain the path to the file annotated
80
81
        if log_format is XMLLogFormatter:
82
            print >>sys.stdout, '<?xml version="1.0"?>'
83
            print >>sys.stdout, '<logs>'
84
            log_class.run(self, location=location, timezone=timezone, 
85
                    verbose=verbose, show_ids=show_ids, forward=forward, 
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
86
                    revision=revision, log_format=log_format, message=message, limit=limit)
18 by Guillermo Gonzalez
* support for merge and changed files
87
            # workaround
88
            print >>sys.stdout, '</log>'
9 by Guillermo Gonzalez
* Added file attribute to annotation, which contain the path to the file annotated
89
            print >>sys.stdout, '</logs>'
90
        else:
91
            log_class.run(self, location=location, timezone=timezone, 
92
                    verbose=verbose, show_ids=show_ids, forward=forward, 
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
93
                    revision=revision, log_format=log_format, message=message, limit=limit)
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
94
18.1.1 by Martin Albisetti
Added initial support for "missing" command
95
96
class cmd_missing(builtins.cmd_missing):
97
    __doc__ = builtins.cmd_missing.__doc__
98
    
99
    @display_command
100
    def run(self, verbose=False,
101
            show_ids=False,
102
						delta=False,
103
            log_format=None):
104
105
        if log_format is XMLLogFormatter:
106
            print >>sys.stdout, '<?xml version="1.0"?>'
107
            print >>sys.stdout, '<logs>'
108
            missing_class.run(self, verbose=verbose, show_ids=show_ids, log_format=log_format)
109
            # workaround
110
            print >>sys.stdout, '</log>'
111
            print >>sys.stdout, '</logs>'
112
        else:
113
            missing_class.run(self, verbose=verbose, show_ids=show_ids, log_format=log_format)
114
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
115
class XMLLogFormatter(LogFormatter):
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
116
    """ add a --xml format to 'bzr log'"""
18 by Guillermo Gonzalez
* support for merge and changed files
117
    import xml.dom.minidom as minidom
13 by Guillermo Gonzalez
Applied patch for Bug #119882 (thanks LarstiQ)
118
15 by Guillermo Gonzalez
* Fix Bug #124929 - added support_merge_revisions and support_tags
119
    supports_merge_revisions = True
13 by Guillermo Gonzalez
Applied patch for Bug #119882 (thanks LarstiQ)
120
    supports_delta = True
15 by Guillermo Gonzalez
* Fix Bug #124929 - added support_merge_revisions and support_tags
121
    supports_tags = True
18 by Guillermo Gonzalez
* support for merge and changed files
122
    log_count = 0
13 by Guillermo Gonzalez
Applied patch for Bug #119882 (thanks LarstiQ)
123
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
124
    def __init__(self, to_file, show_ids=False, show_timezone='original'):
4 by Guillermo Gonzalez
Fix some lines lenght and typos
125
        super(XMLLogFormatter, self).__init__(to_file=to_file, 
126
                               show_ids=show_ids, show_timezone=show_timezone)
18 by Guillermo Gonzalez
* support for merge and changed files
127
        self.is_merge = False
128
        #self.real_to_file = to_file
129
        #self.to_file = StringIO.StringIO()
130
        self.is_first = True
131
        log_count = 0
13 by Guillermo Gonzalez
Applied patch for Bug #119882 (thanks LarstiQ)
132
        
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
133
    def show(self, revno, rev, delta, tags=None):
134
        lr = LogRevision(rev, revno, 0, delta, tags)
135
        return self.log_revision(lr)
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
136
137
    def show_merge_revno(self, rev, merge_depth, revno):
138
        """a call to self._show_helper, XML don't care about formatting """
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
139
        lr = LogRevision(rev, merge_depth=merge_depth, revno=revno)
140
        return self.log_revision(lr)
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
141
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
142
    def log_revision(self, revision):
143
        """Log a revision, either merged or not."""
3 by Guillermo Gonzalez
Added (xml)escaping usign xml.sax.saxutils
144
        from xml.sax import saxutils
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
145
        from bzrlib.osutils import format_date
18 by Guillermo Gonzalez
* support for merge and changed files
146
        #indent = '    '*revision.merge_depth
147
        to_file = self.to_file
148
        # to handle merge revision as childs
149
        if revision.merge_depth > 0:
150
            if not self.is_merge:
151
                print >>to_file,  '<merge>',
152
                self.is_merge = True
153
            print >>to_file,  '<log>',
154
            self.__log_revision(revision)
155
            print >>to_file,  '</log>',
156
        else:
157
            if self.is_merge:
158
                print >>to_file,  '</merge>',
159
                self.is_merge = False
160
            if not self.is_first:
161
                print >>to_file,  '</log>',
162
            print >>to_file,  '<log>',
163
            self.__log_revision(revision)
164
        if self.is_first:
165
            self.is_first = False
166
        XMLLogFormatter.log_count = XMLLogFormatter.log_count + 1
167
168
    def __log_revision(self, revision):
169
        from xml.sax import saxutils
170
        from bzrlib.osutils import format_date
171
        import StringIO
172
        #to_file = StringIO.StringIO()
173
        to_file = self.to_file
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
174
        if revision.revno is not None:
175
            print >>to_file,  '<revno>%s</revno>' % revision.revno,
176
        if revision.tags:
177
            print >>to_file,  '<tags>'
178
            for tag in revision.tags:
179
                print >>to_file, indent+'<tag>%s</tag>' % tag
180
            print >>to_file,  '</tags>'
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
181
        if self.show_ids:
17 by Guillermo Gonzalez
* patch provided by beuno for Bug #132316 applied
182
            print >>to_file,  '<revisionid>%s</revisionid>' % revision.rev.revision_id,
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
183
            if len(revision.rev.parent_ids) > 0:
3 by Guillermo Gonzalez
Added (xml)escaping usign xml.sax.saxutils
184
                print >>to_file, '<parents>',
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
185
            for parent_id in revision.rev.parent_ids:
3 by Guillermo Gonzalez
Added (xml)escaping usign xml.sax.saxutils
186
                print >>to_file, '<parent>%s</parent>' % parent_id,
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
187
            if len(revision.rev.parent_ids) > 0:
3 by Guillermo Gonzalez
Added (xml)escaping usign xml.sax.saxutils
188
                print >>to_file, '</parents>',
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
189
4 by Guillermo Gonzalez
Fix some lines lenght and typos
190
        print >>to_file,  '<committer>%s</committer>' % \
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
191
                        saxutils.escape(revision.rev.committer),
192
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
193
        try:
194
            print >>to_file, '<branch-nick>%s</branch-nick>' % \
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
195
                saxutils.escape(revision.rev.properties['branch-nick']),
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
196
        except KeyError:
197
            pass
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
198
        date_str = format_date(revision.rev.timestamp,
199
                               revision.rev.timezone or 0,
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
200
                               self.show_timezone)
5 by Guillermo Gonzalez
fix typo in <timestamp> tag
201
        print >>to_file,  '<timestamp>%s</timestamp>' % date_str,
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
202
3 by Guillermo Gonzalez
Added (xml)escaping usign xml.sax.saxutils
203
        print >>to_file,  '<message>',
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
204
        if not revision.rev.message:
205
            print >>to_file,  indent+'(no message)'
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
206
        else:
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
207
            message = revision.rev.message.rstrip('\r\n')
208
            for l in message.split('\n'):
209
                print >>to_file, saxutils.escape(l)
210
            #print >>to_file,  saxutils.escape(rev.message),
3 by Guillermo Gonzalez
Added (xml)escaping usign xml.sax.saxutils
211
        print >>to_file,  '</message>',
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
212
        if revision.delta is not None:
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
213
            from statusxml import show_tree_xml
18 by Guillermo Gonzalez
* support for merge and changed files
214
            print >>to_file,  '<affected-files>',
13 by Guillermo Gonzalez
Applied patch for Bug #119882 (thanks LarstiQ)
215
            show_tree_xml(revision.delta, to_file, self.show_ids)
18 by Guillermo Gonzalez
* support for merge and changed files
216
            print >>to_file,  '</affected-files>',
217
        #print >>to_file,  '</log>',
218
        #return to_file
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
219
7 by Guillermo Gonzalez
* Fixed annotation --xml, now always is executed with --all and --long
220
status_class = register_command(cmd_status, decorate=True)
221
annotate_class = register_command(cmd_annotate, decorate=True)
18.1.1 by Martin Albisetti
Added initial support for "missing" command
222
missing_class = register_command(cmd_missing, decorate=True)
9 by Guillermo Gonzalez
* Added file attribute to annotation, which contain the path to the file annotated
223
log_class = register_command(cmd_log, decorate=True)
2 by Guillermo Gonzalez
Added --xml option to log, the xml is not well formed, but this is the cleaner way I found
224
log_formatter_registry.register('xml', XMLLogFormatter,
12 by Guillermo Gonzalez
- XMLLogFormatter modified to comply with 0.17 LogFormatter interface
225
                              'Detailed (not well formed?) XML log format')
6 by Guillermo Gonzalez
* stausxml new implemented as --xml option to status command
226
227
228