~piastucki/bzr-xmloutput/xml-log-fix

« back to all changes in this revision

Viewing changes to cmds.py

  • Committer: Guillermo Gonzalez
  • Author(s): Jelmer Vernooij
  • Date: 2011-03-09 23:05:27 UTC
  • mfrom: (150.2.1 trunk)
  • Revision ID: guillo.gonzo@gmail.com-20110309230527-lqwt272otza8s6rt
Lazily load bzr-xmloutput commands.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# Copyright (C) 2007-2009 Guillermo Gonzalez
 
3
#
 
4
# The code taken from bzrlib is under: Copyright (C) 2005-2007 Canonical Ltd
 
5
#
 
6
# This program is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 2 of the License, or
 
9
# (at your option) any later version.
 
10
#
 
11
# This program is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with this program; if not, write to the Free Software
 
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 
19
#
 
20
# Contributors:
 
21
#               Martin Albisetti
 
22
 
 
23
import info
 
24
import bzrlib
 
25
from bzrlib.lazy_import import lazy_import
 
26
lazy_import(globals(), """
 
27
import sys
 
28
from bzrlib import (
 
29
    builtins,
 
30
    bzrdir,
 
31
    commands,
 
32
    option,
 
33
    log,
 
34
    workingtree,
 
35
    errors
 
36
    )
 
37
 
 
38
from bzrlib.option import Option, custom_help
 
39
from bzrlib.commands import display_command
 
40
import logxml
 
41
import service
 
42
import socket
 
43
from xml_errors import handle_error_xml
 
44
""")
 
45
 
 
46
 
 
47
version_info = info.bzr_plugin_version
 
48
plugin_name = info.bzr_plugin_name
 
49
 
 
50
null_option = option.Option('null',
 
51
                            help='Write an ascii NUL (\\0) as the final char.')
 
52
 
 
53
 
 
54
class cmd_xmlstatus(commands.Command):
 
55
    """Display status summary.
 
56
 
 
57
    This reports on versioned and unknown files, reporting them
 
58
    grouped by state.  Possible states are:
 
59
 
 
60
    added
 
61
        Versioned in the working copy but not in the previous revision.
 
62
 
 
63
    removed
 
64
        Versioned in the previous revision but removed or deleted
 
65
        in the working copy.
 
66
 
 
67
    renamed
 
68
        Path of this file changed from the previous revision;
 
69
        the text may also have changed.  This includes files whose
 
70
        parent directory was renamed.
 
71
 
 
72
    modified
 
73
        Text has changed since the previous revision.
 
74
 
 
75
    kind changed
 
76
        File kind has been changed (e.g. from file to directory).
 
77
 
 
78
    unknown
 
79
        Not versioned and not matching an ignore pattern.
 
80
 
 
81
    To see ignored files use 'bzr ignored'.  For details on the
 
82
    changes to file texts, use 'bzr diff'.
 
83
 
 
84
    Note that --short or -S gives status flags for each item, similar
 
85
    to Subversion's status command. To get output similar to svn -q,
 
86
    use bzr -SV.
 
87
 
 
88
    If no arguments are specified, the status of the entire working
 
89
    directory is shown.  Otherwise, only the status of the specified
 
90
    files or directories is reported.  If a directory is given, status
 
91
    is reported for everything inside that directory.
 
92
 
 
93
    If a revision argument is given, the status is calculated against
 
94
    that revision, or between two revisions if two are provided.
 
95
    """
 
96
    hidden = True
 
97
    takes_args = ['file*']
 
98
    takes_options = ['show-ids', 'revision', 'change',
 
99
                     Option('versioned', help='Only show versioned files.',
 
100
                            short_name='V'),
 
101
                     null_option
 
102
                     ]
 
103
    encoding_type = 'replace'
 
104
 
 
105
    @display_command
 
106
    @handle_error_xml
 
107
    def run(self, file_list=None, revision=None, versioned=False, null=False):
 
108
        from statusxml import show_tree_status_xml
 
109
        tree, file_list = builtins.tree_files(file_list)
 
110
        to_file = self.outf
 
111
        if to_file is None:
 
112
            to_file = sys.stdout
 
113
        show_tree_status_xml(tree, show_ids=True,
 
114
            specific_files=file_list, revision=revision,
 
115
            to_file=to_file, versioned=versioned)
 
116
        if null:
 
117
            to_file.write('\0')
 
118
        self.outf.write('\n')
 
119
 
 
120
 
 
121
class cmd_xmlannotate(commands.Command):
 
122
    """Show the origin of each line in a file.
 
123
 
 
124
    This prints out the given file with an annotation on the left side
 
125
    indicating which revision, author and date introduced the change.
 
126
 
 
127
    If the origin is the same for a run of consecutive lines, it is
 
128
    shown only at the top, unless the --all option is given.
 
129
    """
 
130
    hidden = True
 
131
    takes_args = ['filename']
 
132
    takes_options = ['revision', 'show-ids', null_option]
 
133
 
 
134
    encoding_type = 'exact'
 
135
 
 
136
    @display_command
 
137
    @handle_error_xml
 
138
    def run(self, filename, revision=None, show_ids=False, null=False):
 
139
        from annotatexml import annotate_file_xml
 
140
        wt, branch, relpath = \
 
141
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
142
        if wt is not None:
 
143
            wt.lock_read()
 
144
        else:
 
145
            branch.lock_read()
 
146
        wt_root_path = wt.id2abspath(wt.get_root_id())
 
147
        try:
 
148
            if revision is None:
 
149
                revision_id = branch.last_revision()
 
150
            elif len(revision) != 1:
 
151
                raise bzrlib.errors.BzrCommandError(
 
152
                    'xmlannotate --revision takes exactly 1 argument')
 
153
            else:
 
154
                revision_id = revision[0].in_history(branch).rev_id
 
155
            tree = branch.repository.revision_tree(revision_id)
 
156
            if wt is not None:
 
157
                file_id = wt.path2id(relpath)
 
158
            else:
 
159
                file_id = tree.path2id(relpath)
 
160
            if file_id is None:
 
161
                raise bzrlib.errors.NotVersionedError(filename)
 
162
 
 
163
            file_version = tree.inventory[file_id].revision
 
164
            # always run with --all and --long options
 
165
            # to get the author of each line
 
166
            annotate_file_xml(branch=branch, rev_id=file_version,
 
167
                    file_id=file_id, to_file=self.outf, show_ids=show_ids,
 
168
                    wt_root_path=wt_root_path, file_path=relpath)
 
169
            if null:
 
170
                self.outf.write('\0')
 
171
            self.outf.write('\n')
 
172
        finally:
 
173
            if wt is not None:
 
174
                wt.unlock()
 
175
            else:
 
176
                branch.unlock()
 
177
 
 
178
 
 
179
class cmd_xmlmissing(commands.Command):
 
180
    """Show unmerged/unpulled revisions between two branches.
 
181
 
 
182
    OTHER_BRANCH may be local or remote.
 
183
    """
 
184
    hidden = True
 
185
    takes_args = ['other_branch?']
 
186
    takes_options = [
 
187
            Option('reverse', 'Reverse the order of revisions.'),
 
188
            Option('mine-only',
 
189
                   'Display changes in the local branch only.'),
 
190
            Option('this' , 'Same as --mine-only.'),
 
191
            Option('theirs-only',
 
192
                   'Display changes in the remote branch only.'),
 
193
            Option('other', 'Same as --theirs-only.'),
 
194
            'show-ids',
 
195
            'verbose',
 
196
            null_option
 
197
            ]
 
198
    encoding_type = 'replace'
 
199
 
 
200
    @display_command
 
201
    @handle_error_xml
 
202
    def run(self, *args, **kwargs):
 
203
        from missingxml import show_missing_xml
 
204
 
 
205
        if self.outf is None:
 
206
            self.outf = sys.stdout
 
207
 
 
208
        show_missing_xml(self, log_format=logxml.XMLLogFormatter,
 
209
                         *args, **kwargs)
 
210
        if getattr(kwargs, 'null', False):
 
211
            self.outf.write('\0')
 
212
        self.outf.write('\n')
 
213
 
 
214
 
 
215
class cmd_xmlinfo(commands.Command):
 
216
    """Show information about a working tree, branch or repository.
 
217
 
 
218
    This command will show all known locations and formats associated to the
 
219
    tree, branch or repository.  Statistical information is included with
 
220
    each report.
 
221
 
 
222
    Branches and working trees will also report any missing revisions.
 
223
    """
 
224
    hidden = True
 
225
    takes_args = ['location?']
 
226
    takes_options = ['verbose', null_option]
 
227
    encoding_type = 'replace'
 
228
 
 
229
    @display_command
 
230
    @handle_error_xml
 
231
    def run(self, *args, **kwargs):
 
232
        location = None
 
233
        if kwargs.has_key('location'):
 
234
            location = kwargs['location']
 
235
        if kwargs.has_key('verbose') and kwargs['verbose']:
 
236
            noise_level = 2
 
237
        else:
 
238
            noise_level = 0
 
239
        from infoxml import show_bzrdir_info_xml
 
240
        if location != None:
 
241
            from bzrlib.urlutils import normalize_url
 
242
            location = normalize_url(location)
 
243
        show_bzrdir_info_xml(bzrdir.BzrDir.open_containing(location)[0],
 
244
                             verbose=noise_level, outfile=self.outf)
 
245
        if getattr(kwargs, 'null', False):
 
246
            self.outf.write('\0')
 
247
        self.outf.write('\n')
 
248
 
 
249
 
 
250
class cmd_xmlplugins(commands.Command):
 
251
    """List the installed plugins.
 
252
 
 
253
    This command displays the list of installed plugins including
 
254
    version of plugin and a short description of each.
 
255
 
 
256
    """
 
257
    hidden = True
 
258
    takes_options = ['verbose', null_option]
 
259
 
 
260
    @display_command
 
261
    @handle_error_xml
 
262
    def run(self, *args, **kwargs):
 
263
        import bzrlib.plugin
 
264
        from inspect import getdoc
 
265
        if self.outf is None:
 
266
            self.outf = sys.stdout
 
267
 
 
268
        self.outf.write('<?xml version="1.0" encoding="%s"?>' % \
 
269
                bzrlib.osutils.get_user_encoding())
 
270
        self.outf.write('<plugins>')
 
271
        from writer import _escape_cdata
 
272
        for name, plugin in bzrlib.plugin.plugins().items():
 
273
            self.outf.write('<plugin>')
 
274
            self.outf.write('<name>%s</name>' % name)
 
275
            self.outf.write('<version>%s</version>' % plugin.__version__)
 
276
            self.outf.write('<path>%s</path>' % plugin.path())
 
277
            d = getdoc(plugin.module)
 
278
            if d:
 
279
                self.outf.write('<doc>%s</doc>' % _escape_cdata(d))
 
280
            self.outf.write('</plugin>')
 
281
        self.outf.write('</plugins>')
 
282
        if getattr(kwargs, 'null', False):
 
283
            self.outf.write('\0')
 
284
        self.outf.write('\n')
 
285
 
 
286
 
 
287
class cmd_xmlversion(commands.Command):
 
288
    """Show version of bzr."""
 
289
    hidden = True
 
290
    encoding_type = 'replace'
 
291
    takes_options = [Option("short", help="Only print the version number."),
 
292
                    null_option]
 
293
 
 
294
    @display_command
 
295
    @handle_error_xml
 
296
    def run(self, short=False, null=False):
 
297
        from versionxml import show_version_xml
 
298
        to_file = self.outf
 
299
        if to_file is None:
 
300
            to_file = sys.stdout
 
301
        self.outf.write('<?xml version="1.0" encoding="%s"?>' % \
 
302
                bzrlib.osutils.get_user_encoding())
 
303
        if short:
 
304
            to_file.write("<version><bazaar><version>" + \
 
305
            bzrlib.version_string + \
 
306
            "</version></bazaar></version>")
 
307
        else:
 
308
            show_version_xml(to_file=to_file)
 
309
        if null:
 
310
            to_file.write('\0')
 
311
        to_file.write('\n')
 
312
 
 
313
 
 
314
def xmllog_options():
 
315
    # Take a copy of the log options before modifying it
 
316
    opts = builtins.cmd_log.takes_options[:]
 
317
    opts.append(null_option)
 
318
    # Remove log_format since we requires our own
 
319
    opts.remove('log-format')
 
320
    return opts
 
321
 
 
322
 
 
323
class cmd_xmllog(builtins.cmd_log):
 
324
    """Show log of a branch, file, or directory as XML."""
 
325
    hidden = True
 
326
 
 
327
    takes_options = xmllog_options()
 
328
 
 
329
    @display_command
 
330
    @handle_error_xml
 
331
    def run(self, *args, **kwargs):
 
332
        # Force our specific formatter
 
333
        kwargs['log_format'] = logxml.XMLLogFormatter
 
334
        # Filter out our specific option
 
335
        try:
 
336
            null = kwargs.pop('null')
 
337
        except KeyError:
 
338
            null = False
 
339
        exit_val =  builtins.cmd_log.run(self, *args, **kwargs)
 
340
        if null:
 
341
            self.outf.write('\0')
 
342
        self.outf.write('\n')
 
343
        return exit_val
 
344
 
 
345
 
 
346
class cmd_xmlls(builtins.cmd_ls):
 
347
    """XML representation of the list of files in a tree.
 
348
    """
 
349
 
 
350
    hidden = True
 
351
    _see_also = ['xmlstatus']
 
352
    takes_args = ['path?']
 
353
    # TODO: Take a revision or remote path and list that tree instead.
 
354
    takes_options = [
 
355
            'verbose',
 
356
            'revision',
 
357
            Option('non-recursive',
 
358
                   help='Don\'t recurse into subdirectories.'),
 
359
            Option('from-root',
 
360
                   help='Print paths relative to the root of the branch.'),
 
361
            Option('unknown', help='Print unknown files.'),
 
362
            Option('versioned', help='Print versioned files.',
 
363
                   short_name='V'),
 
364
            Option('ignored', help='Print ignored files.'),
 
365
            Option('kind',
 
366
                   help='List entries of a particular kind: file, ' + \
 
367
                   'directory, symlink.',
 
368
                   type=unicode),
 
369
            null_option
 
370
            ]
 
371
    encoding_type = 'replace'
 
372
 
 
373
 
 
374
    @display_command
 
375
    @handle_error_xml
 
376
    def run(self, *args, **kwargs):
 
377
        import lsxml
 
378
        self.outf.write('<?xml version="1.0" encoding="%s"?>' % \
 
379
                bzrlib.osutils.get_user_encoding())
 
380
        lsxml.show_ls_xml(self.outf, *args, **kwargs)
 
381
        if getattr(kwargs, 'null', False):
 
382
            self.outf.write('\0')
 
383
        self.outf.write('\n')
 
384
 
 
385
class cmd_start_xmlrpc(commands.Command):
 
386
    """Start the xmlrpc service."""
 
387
 
 
388
    hidden = True
 
389
    takes_options = [
 
390
            Option('hostname', argname='HOSTNAME', type=str,
 
391
                help='Use the specified hostname, defaults to localhost.'),
 
392
            Option('port', argname='PORT', type=int,
 
393
                help='Use the specified port, defaults to 11111.'),
 
394
            'verbose',
 
395
            ]
 
396
 
 
397
    @display_command
 
398
    def run(self, port=11111, hostname='localhost', verbose=False):
 
399
        if hostname is None:
 
400
            hostname = socket.gethostname()
 
401
 
 
402
        if verbose:
 
403
            self.outf.write('Listening on http://'+hostname+':'+str(port)+'\n')
 
404
            self.outf.flush()
 
405
 
 
406
        self.server = service.BzrXMLRPCServer((hostname, port),
 
407
                                     logRequests=verbose, to_file=self.outf)
 
408
 
 
409
        try:
 
410
            self.server.serve_forever()
 
411
        finally:
 
412
            self.server.shutdown()
 
413
 
 
414
 
 
415
class cmd_stop_xmlrpc(commands.Command):
 
416
    """Stops a xmlrpc service."""
 
417
 
 
418
    hidden = True
 
419
    takes_options = [
 
420
            Option('hostname', argname='HOSTNAME', type=str,
 
421
                help='Use the specified hostname, defaults to localhost.'),
 
422
            Option('port', argname='PORT', type=int,
 
423
                help='Use the specified port, defaults to 11111.'),
 
424
            'verbose',
 
425
            ]
 
426
 
 
427
    @display_command
 
428
    def run(self, port=11111, hostname='localhost', verbose=False):
 
429
        url = "http://"+hostname+":"+str(port)
 
430
        if verbose:
 
431
            self.outf.write('Stopping xmlrpc service on ' + url + '\n')
 
432
            self.outf.flush()
 
433
        from xmlrpclib import Server
 
434
        server = Server(url)
 
435
        server.quit()