source: tailor/vcpx/changes.py @ 231

Revision 231, 4.6 KB checked in by lele@…, 8 years ago (diff)

New option to disable refilling of changelogs
With --dont-refill-changelogs tailor won't refill the changelog of the
changeset it collects.

Line 
1#! /usr/bin/python
2# -*- mode: python; coding: utf-8 -*-
3# :Progetto: vcpx -- Changesets
4# :Creato:   ven 11 giu 2004 15:31:18 CEST
5# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
6#
7
8"""
9Changesets are an object representation of a set of changes to some files.
10"""
11
12__docformat__ = 'reStructuredText'
13
14class ChangesetEntry(object):
15    """
16    Represent a changed entry in a Changeset.
17
18    For our scope, this simply means an entry `name`, the original
19    `old_revision`, the `new_revision` after this change, an
20    `action_kind` to denote the kind of change, and finally a `status`
21    to indicate possible conflicts.
22    """
23   
24    ADDED = 'A'
25    DELETED = 'D'
26    UPDATED = 'U'
27    RENAMED = 'R'
28
29    APPLIED = 'A'
30    CONFLICT = 'C'
31   
32    __slots__ = ('name', 'old_name',
33                 'old_revision', 'new_revision',
34                 'action_kind', 'status')
35
36    def __init__(self, name):
37        self.name = name
38        self.old_name = None
39        self.old_revision = None
40        self.new_revision = None
41        self.action_kind = None
42        self.status = None
43
44    def __str__(self):
45        if self.action_kind == self.ADDED:
46            return '%s (new at %s)' % (self.name, self.new_revision)
47        elif self.action_kind == self.DELETED:
48            return '%s (deleted)' % self.name
49        elif self.action_kind == self.UPDATED:
50            return "%s (update to %s)" % (self.name,
51                                          self.new_revision)
52        else:
53            return '%s (rename from %s)' % (self.name, self.old_name)
54
55
56from textwrap import TextWrapper
57from re import compile, MULTILINE
58   
59itemize_re = compile('^[ ]*[-*] ', MULTILINE)
60
61def refill(msg):
62    """
63    Refill a changelog message.
64
65    Normalize the message reducing multiple spaces and newlines to single
66    spaces, recognizing common form of `bullet lists`, that is paragraphs
67    starting with either a dash "-" or an asterisk "*".
68    """
69   
70    wrapper = TextWrapper()
71    res = []
72    items = itemize_re.split(msg.strip())
73   
74    if len(items)>1:
75        # Remove possible first empty split, when the message immediately
76        # starts with a bullet
77        if not items[0]:
78            del items[0]
79           
80        if len(items)>1:
81            wrapper.initial_indent = '- '
82            wrapper.subsequent_indent = ' '*2
83               
84    for item in items:
85        if item:
86            words = filter(None, item.strip().replace('\n', ' ').split(' '))
87            normalized = ' '.join(words)
88            res.append(wrapper.fill(normalized))
89
90    return '\n\n'.join(res)
91
92
93class Changeset(object):
94    """
95    Represent a single upstream Changeset.
96
97    This is a container of each file affected by this revision of the tree.
98    """
99
100    REFILL_MESSAGE = True
101    """Refill changelogs"""
102   
103    def __init__(self, revision, date, author, log, entries=None, **other):
104        """
105        Initialize a new ChangeSet.
106        """
107       
108        self.revision = revision
109        self.date = date
110        self.author = author
111        if self.REFILL_MESSAGE:
112            self.log = refill(log)
113        else:
114            self.log = log
115        self.entries = entries or []
116
117    def addEntry(self, entry, revision):
118        """
119        Facility to add an entry.
120        """
121
122        e = ChangesetEntry(entry)
123        e.new_revision = revision
124        self.entries.append(e)
125        return e
126   
127    def __str__(self):
128        s = []
129        s.append('Revision: %s' % self.revision)
130        s.append('Date: %s' % str(self.date))
131        s.append('Author: %s' % self.author)
132        for ak in ['Added', 'Modified', 'Removed', 'Renamed']:
133            entries = getattr(self, ak.lower()+'Entries')()
134            if entries:
135                s.append('%s: %s' % (ak, ','.join([e.name
136                                                   for e in entries])))
137        s.append('Log: %s' % self.log)
138        return '\n'.join(s)
139
140    def addedEntries(self):
141        """
142        Filter the changesets and extract the added entries.
143        """
144       
145        return [e for e in self.entries if e.action_kind == e.ADDED]
146
147    def modifiedEntries(self):
148        """
149        Filter the changesets and extract the modified entries.
150        """
151
152        return [e for e in self.entries if e.action_kind == e.UPDATED]
153
154    def removedEntries(self):
155        """
156        Filter the changesets and extract the deleted entries.
157        """
158
159        return [e for e in self.entries if e.action_kind == e.DELETED]
160
161    def renamedEntries(self):
162        """
163        Filter the changesets and extract the renamed entries.
164        """
165
166        return [e for e in self.entries if e.action_kind == e.RENAMED]
Note: See TracBrowser for help on using the repository browser.