To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / lib / redmine / scm / adapters / mercurial / redminehelper.py @ 442:753f1380d6bc

History | View | Annotate | Download (7.67 KB)

1 245:051f544170fe Chris
# redminehelper: Redmine helper extension for Mercurial
2
#
3
# Copyright 2010 Alessio Franceschelli (alefranz.net)
4
# Copyright 2010-2011 Yuya Nishihara <yuya@tcha.org>
5
#
6
# This software may be used and distributed according to the terms of the
7
# GNU General Public License version 2 or any later version.
8
"""helper commands for Redmine to reduce the number of hg calls
9

10
To test this extension, please try::
11

12
    $ hg --config extensions.redminehelper=redminehelper.py rhsummary
13

14
I/O encoding:
15

16
:file path: urlencoded, raw string
17
:tag name: utf-8
18
:branch name: utf-8
19
:node: 12-digits (short) hex string
20

21
Output example of rhsummary::
22

23
    <?xml version="1.0"?>
24
    <rhsummary>
25
      <repository root="/foo/bar">
26
        <tip revision="1234" node="abcdef0123..."/>
27
        <tag revision="123" node="34567abc..." name="1.1.1"/>
28
        <branch .../>
29
        ...
30
      </repository>
31
    </rhsummary>
32

33
Output example of rhmanifest::
34

35
    <?xml version="1.0"?>
36
    <rhmanifest>
37
      <repository root="/foo/bar">
38
        <manifest revision="1234" path="lib">
39
          <file name="diff.rb" revision="123" node="34567abc..." time="12345"
40
                 size="100"/>
41
          ...
42
          <dir name="redmine"/>
43
          ...
44
        </manifest>
45
      </repository>
46
    </rhmanifest>
47
"""
48
import re, time, cgi, urllib
49
from mercurial import cmdutil, commands, node, error
50
51
_x = cgi.escape
52
_u = lambda s: cgi.escape(urllib.quote(s))
53
54
def _tip(ui, repo):
55
    # see mercurial/commands.py:tip
56
    def tiprev():
57
        try:
58
            return len(repo) - 1
59
        except TypeError:  # Mercurial < 1.1
60
            return repo.changelog.count() - 1
61
    tipctx = repo.changectx(tiprev())
62
    ui.write('<tip revision="%d" node="%s"/>\n'
63
             % (tipctx.rev(), _x(node.short(tipctx.node()))))
64
65
_SPECIAL_TAGS = ('tip',)
66
67
def _tags(ui, repo):
68
    # see mercurial/commands.py:tags
69
    for t, n in reversed(repo.tagslist()):
70
        if t in _SPECIAL_TAGS:
71
            continue
72
        try:
73
            r = repo.changelog.rev(n)
74
        except error.LookupError:
75
            continue
76
        ui.write('<tag revision="%d" node="%s" name="%s"/>\n'
77
                 % (r, _x(node.short(n)), _x(t)))
78
79
def _branches(ui, repo):
80
    # see mercurial/commands.py:branches
81
    def iterbranches():
82
        for t, n in repo.branchtags().iteritems():
83
            yield t, n, repo.changelog.rev(n)
84
    def branchheads(branch):
85
        try:
86
            return repo.branchheads(branch, closed=False)
87
        except TypeError:  # Mercurial < 1.2
88
            return repo.branchheads(branch)
89
    for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
90
        if repo.lookup(r) in branchheads(t):
91
            ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
92
                     % (r, _x(node.short(n)), _x(t)))
93
94
def _manifest(ui, repo, path, rev):
95
    ctx = repo.changectx(rev)
96
    ui.write('<manifest revision="%d" path="%s">\n'
97
             % (ctx.rev(), _u(path)))
98
99
    known = set()
100
    pathprefix = (path.rstrip('/') + '/').lstrip('/')
101
    for f, n in sorted(ctx.manifest().iteritems(), key=lambda e: e[0]):
102
        if not f.startswith(pathprefix):
103
            continue
104
        name = re.sub(r'/.*', '/', f[len(pathprefix):])
105
        if name in known:
106
            continue
107
        known.add(name)
108
109
        if name.endswith('/'):
110
            ui.write('<dir name="%s"/>\n'
111
                     % _x(urllib.quote(name[:-1])))
112
        else:
113
            fctx = repo.filectx(f, fileid=n)
114
            tm, tzoffset = fctx.date()
115
            ui.write('<file name="%s" revision="%d" node="%s" '
116
                     'time="%d" size="%d"/>\n'
117
                     % (_u(name), fctx.rev(), _x(node.short(fctx.node())),
118
                        tm, fctx.size(), ))
119
120
    ui.write('</manifest>\n')
121
122
def rhannotate(ui, repo, *pats, **opts):
123 441:cbce1fd3b1b7 Chris
    rev = urllib.unquote_plus(opts.pop('rev', None))
124
    opts['rev'] = rev
125 245:051f544170fe Chris
    return commands.annotate(ui, repo, *map(urllib.unquote_plus, pats), **opts)
126
127
def rhcat(ui, repo, file1, *pats, **opts):
128 441:cbce1fd3b1b7 Chris
    rev = urllib.unquote_plus(opts.pop('rev', None))
129
    opts['rev'] = rev
130 245:051f544170fe Chris
    return commands.cat(ui, repo, urllib.unquote_plus(file1), *map(urllib.unquote_plus, pats), **opts)
131
132
def rhdiff(ui, repo, *pats, **opts):
133
    """diff repository (or selected files)"""
134
    change = opts.pop('change', None)
135
    if change:  # add -c option for Mercurial<1.1
136
        base = repo.changectx(change).parents()[0].rev()
137
        opts['rev'] = [str(base), change]
138
    opts['nodates'] = True
139
    return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
140
141 441:cbce1fd3b1b7 Chris
def rhlog(ui, repo, *pats, **opts):
142
    rev      = opts.pop('rev')
143
    bra0     = opts.pop('branch')
144
    from_rev = urllib.unquote_plus(opts.pop('from', None))
145
    to_rev   = urllib.unquote_plus(opts.pop('to'  , None))
146
    bra      = urllib.unquote_plus(opts.pop('rhbranch', None))
147
    from_rev = from_rev.replace('"', '\\"')
148
    to_rev   = to_rev.replace('"', '\\"')
149
    opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)]
150
    opts['branch'] = [bra]
151
    return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts)
152
153 245:051f544170fe Chris
def rhmanifest(ui, repo, path='', **opts):
154
    """output the sub-manifest of the specified directory"""
155
    ui.write('<?xml version="1.0"?>\n')
156
    ui.write('<rhmanifest>\n')
157
    ui.write('<repository root="%s">\n' % _u(repo.root))
158
    try:
159
        _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev')))
160
    finally:
161
        ui.write('</repository>\n')
162
        ui.write('</rhmanifest>\n')
163
164
def rhsummary(ui, repo, **opts):
165
    """output the summary of the repository"""
166
    ui.write('<?xml version="1.0"?>\n')
167
    ui.write('<rhsummary>\n')
168
    ui.write('<repository root="%s">\n' % _u(repo.root))
169
    try:
170
        _tip(ui, repo)
171
        _tags(ui, repo)
172
        _branches(ui, repo)
173
        # TODO: bookmarks in core (Mercurial>=1.8)
174
    finally:
175
        ui.write('</repository>\n')
176
        ui.write('</rhsummary>\n')
177
178
# This extension should be compatible with Mercurial 0.9.5.
179
# Note that Mercurial 0.9.5 doesn't have extensions.wrapfunction().
180
cmdtable = {
181
    'rhannotate': (rhannotate,
182
         [('r', 'rev', '', 'revision'),
183
          ('u', 'user', None, 'list the author (long with -v)'),
184
          ('n', 'number', None, 'list the revision number (default)'),
185
          ('c', 'changeset', None, 'list the changeset'),
186
         ],
187
         'hg rhannotate [-r REV] [-u] [-n] [-c] FILE...'),
188
    'rhcat': (rhcat,
189
               [('r', 'rev', '', 'revision')],
190
               'hg rhcat ([-r REV] ...) FILE...'),
191
    'rhdiff': (rhdiff,
192
               [('r', 'rev', [], 'revision'),
193
                ('c', 'change', '', 'change made by revision')],
194
               'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'),
195 441:cbce1fd3b1b7 Chris
    'rhlog': (rhlog,
196
                   [
197
                    ('r', 'rev', [], 'show the specified revision'),
198
                    ('b', 'branch', [],
199
                       'show changesets within the given named branch', 'BRANCH'),
200
                    ('l', 'limit', '',
201
                         'limit number of changes displayed', 'NUM'),
202
                    ('d', 'date', '',
203
                         'show revisions matching date spec', 'DATE'),
204
                    ('u', 'user', [],
205
                      'revisions committed by user', 'USER'),
206
                    ('', 'from', '',
207
                      '', ''),
208
                    ('', 'to', '',
209
                      '', ''),
210
                    ('', 'rhbranch', '',
211
                      '', ''),
212
                    ('', 'template', '',
213
                       'display with template', 'TEMPLATE')],
214
                   'hg rhlog [OPTION]... [FILE]'),
215 245:051f544170fe Chris
    'rhmanifest': (rhmanifest,
216
                   [('r', 'rev', '', 'show the specified revision')],
217
                   'hg rhmanifest [-r REV] [PATH]'),
218
    'rhsummary': (rhsummary, [], 'hg rhsummary'),
219
}