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 / .svn / pristine / 9d / 9dc877e22163cfba0e0ecab2db123574b64de75c.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (7.72 KB)

1
# 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, hg
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
    rev = urllib.unquote_plus(opts.pop('rev', None))
124
    opts['rev'] = rev
125
    return commands.annotate(ui, repo, *map(urllib.unquote_plus, pats), **opts)
126

    
127
def rhcat(ui, repo, file1, *pats, **opts):
128
    rev = urllib.unquote_plus(opts.pop('rev', None))
129
    opts['rev'] = rev
130
    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
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
    if hg.util.version() >= '1.6':
150
      opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)]
151
    else:
152
      opts['rev'] = ['%s:%s' % (from_rev, to_rev)]
153
    opts['branch'] = [bra]
154
    return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts)
155

    
156
def rhmanifest(ui, repo, path='', **opts):
157
    """output the sub-manifest of the specified directory"""
158
    ui.write('<?xml version="1.0"?>\n')
159
    ui.write('<rhmanifest>\n')
160
    ui.write('<repository root="%s">\n' % _u(repo.root))
161
    try:
162
        _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev')))
163
    finally:
164
        ui.write('</repository>\n')
165
        ui.write('</rhmanifest>\n')
166

    
167
def rhsummary(ui, repo, **opts):
168
    """output the summary of the repository"""
169
    ui.write('<?xml version="1.0"?>\n')
170
    ui.write('<rhsummary>\n')
171
    ui.write('<repository root="%s">\n' % _u(repo.root))
172
    try:
173
        _tip(ui, repo)
174
        _tags(ui, repo)
175
        _branches(ui, repo)
176
        # TODO: bookmarks in core (Mercurial>=1.8)
177
    finally:
178
        ui.write('</repository>\n')
179
        ui.write('</rhsummary>\n')
180

    
181
# This extension should be compatible with Mercurial 0.9.5.
182
# Note that Mercurial 0.9.5 doesn't have extensions.wrapfunction().
183
cmdtable = {
184
    'rhannotate': (rhannotate,
185
         [('r', 'rev', '', 'revision'),
186
          ('u', 'user', None, 'list the author (long with -v)'),
187
          ('n', 'number', None, 'list the revision number (default)'),
188
          ('c', 'changeset', None, 'list the changeset'),
189
         ],
190
         'hg rhannotate [-r REV] [-u] [-n] [-c] FILE...'),
191
    'rhcat': (rhcat,
192
               [('r', 'rev', '', 'revision')],
193
               'hg rhcat ([-r REV] ...) FILE...'),
194
    'rhdiff': (rhdiff,
195
               [('r', 'rev', [], 'revision'),
196
                ('c', 'change', '', 'change made by revision')],
197
               'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'),
198
    'rhlog': (rhlog,
199
                   [
200
                    ('r', 'rev', [], 'show the specified revision'),
201
                    ('b', 'branch', [],
202
                       'show changesets within the given named branch'),
203
                    ('l', 'limit', '',
204
                         'limit number of changes displayed'),
205
                    ('d', 'date', '',
206
                         'show revisions matching date spec'),
207
                    ('u', 'user', [],
208
                      'revisions committed by user'),
209
                    ('', 'from', '',
210
                      ''),
211
                    ('', 'to', '',
212
                      ''),
213
                    ('', 'rhbranch', '',
214
                      ''),
215
                    ('', 'template', '',
216
                       'display with template')],
217
                   'hg rhlog [OPTION]... [FILE]'),
218
    'rhmanifest': (rhmanifest,
219
                   [('r', 'rev', '', 'show the specified revision')],
220
                   'hg rhmanifest [-r REV] [PATH]'),
221
    'rhsummary': (rhsummary, [], 'hg rhsummary'),
222
}