~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Copyright 2009-2010 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

# pylint: disable-msg=E0211,E0213

"""Interfaces including and related to IDiff."""

__metaclass__ = type

__all__ = [
    'IDiff',
    'IIncrementalDiff',
    'IPreviewDiff',
    'IStaticDiff',
    'IStaticDiffSource',
    ]

from lazr.restful.declarations import (
    export_as_webservice_entry,
    exported,
    )
from lazr.restful.fields import Reference
from zope.interface import Interface
from zope.schema import (
    Bool,
    Bytes,
    Dict,
    Int,
    Text,
    TextLine,
    )

from canonical.launchpad import _
from lp.code.interfaces.revision import IRevision


class IDiff(Interface):
    """A diff that is stored in the Library."""

    text = Text(
        title=_('Textual contents of a diff.'), readonly=True,
        description=_("The text may be cut off at a defined maximum size."))

    oversized = Bool(
        readonly=True,
        description=_(
            "True if the size of the content is over the defined maximum "
            "size."))

    diff_text = exported(
        Bytes(title=_('Content of this diff'), required=True, readonly=True))

    diff_lines_count = exported(
        Int(title=_('The number of lines in this diff.'), readonly=True))

    diffstat = exported(
        Dict(title=_('Statistics about this diff'), readonly=True))

    added_lines_count = exported(
        Int(title=_('The number of lines added in this diff.'),
            readonly=True))

    removed_lines_count = exported(
        Int(title=_('The number of lines removed in this diff.'),
            readonly=True))


class IIncrementalDiff(Interface):
    """An incremental diff for a merge proposal."""

    diff = Reference(IDiff, title=_('The Diff object.'), readonly=True)

    # The schema for the Reference gets patched in _schema_circular_imports.
    branch_merge_proposal = Reference(
        Interface, readonly=True,
        title=_('The branch merge proposal that diff relates to.'))

    old_revision = Reference(
        IRevision, readonly=True, title=_('The old revision of the diff.'))

    new_revision = Reference(
        IRevision, readonly=True, title=_('The new revision of the diff.'))


class IStaticDiff(Interface):
    """A diff with a fixed value, i.e. between two revisions."""

    from_revision_id = exported(TextLine(readonly=True))

    to_revision_id = exported(TextLine(readonly=True))

    diff = exported(
        Reference(IDiff, title=_('The Diff object.'), readonly=True))

    def destroySelf():
        """Destroy this object."""


class IStaticDiffSource(Interface):
    """Component that can acquire StaticDiffs."""

    def acquire(from_revision_id, to_revision_id, repository, filename=None):
        """Get or create a StaticDiff."""

    def acquireFromText(from_revision_id, to_revision_id, text,
                        filename=None):
        """Get or create a StaticDiff from a string.

        If a StaticDiff exists for this revision_id pair, the text is ignored.

        :param from_revision_id: The id of the old revision.
        :param to_revision_id: The id of the new revision.
        :param text: The text of the diff, as bytes.
        :param filename: The filename to store for the diff.  Randomly
            generated if not supplied.
        """


class IPreviewDiff(IDiff):
    """A diff generated to show actual diff between two branches.

    This diff will be used primarily for branch merge proposals where we are
    trying to determine the effective changes of landing the source branch on
    the target branch.
    """
    export_as_webservice_entry(publish_web_link=False)

    source_revision_id = exported(
        TextLine(
            title=_('The tip revision id of the source branch used to '
                    'generate the diff.'),
            readonly=True))

    target_revision_id = exported(
        TextLine(
            title=_('The tip revision id of the target branch used to '
                    'generate the diff.'),
            readonly=True))

    prerequisite_revision_id = exported(
        TextLine(
            title=_('The tip revision id of the prerequisite branch used to '
                    'generate the diff.'),
            readonly=True))

    conflicts = exported(
        Text(title=_(
                'The conflicts text describing any path or text conflicts.'),
             readonly=True))

    has_conflicts = Bool(
        title=_('Has conflicts'), readonly=True,
        description=_('The previewed merge produces conflicts.'))

    # The schema for the Reference gets patched in _schema_circular_imports.
    branch_merge_proposal = exported(
        Reference(
            Interface, readonly=True,
            title=_('The branch merge proposal that diff relates to.')))

    stale = exported(
        Bool(readonly=True, description=_(
                'If the preview diff is stale, it is out of date when '
                'compared to the tip revisions of the source, target, and '
                'possibly prerequisite branches.')))

    def getFileByName(filename):
        """Return the file under +files with specified name."""