summaryrefslogtreecommitdiff
path: root/linaropy/rn/rnseries.py
blob: 6b6927923c203aa9410d9c68cb32078a87250180 (plain)
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
import unittest
import logging
import os

from sh import ls
from shutil import copyfile

from ..proj import Proj
from ..cd import cd
from ..git.clone import Clone
from ..git.workdir import Workdir
from ..series import Series
from linaroseries import LinaroSeries
from linaroseries import linaroSeriesFromBranchname
from template import RNTemplate

from ..rninput import yninput

# Abstract base class for a release-notes series
# Every RNSeries has a templateRN instance and a workdir.  The template
# instance is used for the base template.


class RNSeries(object):
    # rnremote=u'http://git.linaro.org/toolchain/release-notes.git'
    # use ssh:// so that we can push to the remote.
    rnremote = u'ssh://git@git.linaro.org/toolchain/release-notes.git'
    _series = 'components/toolchain/binaries/README.textile.series'
    # @rnrepo - path to the existing releases notes repository if there is one.
    #           If there isn't one a new one will be cloned.
    # @track_series - an instance of a LinaroSeries to track.
    # @next_series  - an instance of a LinaroSeries that is the next series.

    def __init__(self, proj, rnrepo=None, track_series=None,
                 next_series=None, headless=False):
        self.proj = proj
        # Create the release-notes repository clone.  The Clone constructor
        # will throw an exception if proj is not a Proj.  That is an
        # unrecoverable error so don't catch it here.  The Clone constructor
        # will also throw and exception if rnrepo is not a string.

        if rnrepo:
            logging.info('RNSeries() clone already exists.  Using existing.')
            self.rn_clone = Clone(proj, clonedir=rnrepo)
        else:
            self.rn_clone = Clone(proj, remote=RNSeries.rnremote)

        # TODO: Write a testcase that exposes this.
        if not track_series:
            raise TypeError("Input variable track_series is required.")

        # TODO: Write a testcase that exposes this.
        if not isinstance(track_series, LinaroSeries):
            raise TypeError("Input variable track_series not of type Series.")

        # TODO: Write a testcase that exposes this.
        if not next_series:
            raise TypeError("Input variable next_series is required.")

        # TODO: Write a testcase that exposes this.
        if not isinstance(next_series, LinaroSeries):
            raise TypeError("Input variable next_series not of type Series.")

        self.track_series = track_series
        self.next_series = next_series

        # Default to None, as this is set in update_template_readmes
        self.rn_template = None
        self.rn_series = None

    def update_templ_readmes(self, headless=False):
        """
        Prompt the user to update the Template README.textile files.

        The first time this is called it creates the Template repository.

        This must be called before update_rnseries_reamdes().

        Parameters
        ----------
        headless=False : bool
            Automatically decline to edit any of the README.textile files.
            This is useful for automated testing.  If headless==True then
            the template readmes will not be updated.  Only the template
            repository will be created.
        """
        templ_branchname = self.next_series.shorttype()
        templ_branchname + templ_branchname + "_" + self.next_series.get_dir()
        if not self.rn_template:
            logging.info("Creating the RNTemplate instance.")
            self.rn_template = RNTemplate(
                self.proj,
                self.rn_clone,
                branchname_suffix=templ_branchname)

        logging.info(
            "Requesting updates to the TemplateReadme and series files.")

        self.rn_template.update_readme(headless=headless)
        self.rn_template.update_series(headless=headless)

        logging.info(
            "Commiting README.textile and README.textile.series files to"
            "template repository.")

        return self.rn_template.commit()

    def update_series_readmes(self, headless=False):
        """
        Prompt the user to update the series README.textile.series file.

        The first time this is called it creates the series workdir
        repository.

        The update_template_reamdes() function must be called before this
        is called.

        Exceptions
        ----------
        RuntimeError
            Returned if update_template_readmes() hasn't been called yet.

        Parameters
        ----------
        headless=False : bool
            Automatically decline to edit any of the README.textile files.
            This is useful for automated testing.  If headless==True then
            the template readmes will not be updated.  Only the template
            repository will be created.

        """
        # The RNTemplate instance is necessary as we might need to derive
        # the SeriesRN from it.
        if not self.rn_template:
            raise RuntimeError(
                "The rn_template doesn't yet exist.  Call"
                " update_template_readmes() first.")

        remote_track = self.rn_clone.remote_branchname(
            self.track_series.branchname())
        if not self.rn_series:
            print("Looking for branch %s" % self.track_series.branchname())
            # The workdir for the first candidate series will be derived from
            # the changes made to the master branch templates.  The workdir for
            # subsequent candidates and releases will be made based on the
            # existing candidate or release branch.
            # if not
            # self.rn_clone.branchexists(self.track_series.branchname()):
            if not self.rn_clone.branchexists(remote_track):
                logging.info(
                    "Creating RNSeries based on branch "
                    + self.rn_template.getbranch())

                self.rn_series = Workdir(
                    proj=self.proj,
                    clone=self.rn_clone,
                    workdir=self.next_series.shorttype(),
                    track=self.rn_template.getbranch(),
                    branchname=self.next_series.branchname())
            else:
                logging.info(
                    "MARK Creating RNSeries based on branch "
                    + remote_track)
                # + self.track_series.branchname())

                self.rn_series = Workdir(
                    proj=self.proj,
                    clone=self.rn_clone,
                    workdir=self.next_series.shorttype(),
                    track=remote_track,
                    branchname=self.next_series.branchname())
                # track=self.track_series.branchname(),

                logging.warning(
                    "If you updated the template README.textile.series file"
                    " the changes will not be reflected in this series"
                    " README.textile.series as this series is derived from %s."
                    " Please make the changes to the series"
                    " README.textile.series file as well." %
                    remote_track)
                # self.track_series.branchname())

                # TODO: Ask if the user would like to merge the changes in
                # the template README.textile.series file instead of the
                # long-winded warning above.

        if not headless:
            answer = yninput(
                "Would you like to update the %s README.textile.series"
                " file?" % self.next_series.longlowertype(), "N")
            if answer == "y":
                self.rn_series.edit(self._series)

        return self.rn_series.commit(
            "Added NEWS items for %s." % self.next_series.branchname())

    def push_readme_updates(self):
        pass
        # TODO: Don't forget to push template and workdir changes.
        # self.rn_template.pushToBranch("origin/master")
        # TODO: Should the workdir know where to push to?
        # self.rn_series.pushToBranch(self.next_series.branchname())


class TestSeriesRN(unittest.TestCase):
    pass

if __name__ == '__main__':
    logging.basicConfig(level="INFO")
    unittest.main()