summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan S. Arnold <ryan.arnold@linaro.org>2016-08-20 01:04:53 -0500
committerRyan S. Arnold <ryan.arnold@linaro.org>2016-08-20 01:04:53 -0500
commit737c797232f444acee6462df4deb41ad06be7021 (patch)
treea2297998b694298f167d14724077cbaabfafc508
parent9dac4d48397f5f805e78523f2ee2214b1f09facf (diff)
Add support for generating 'release' release notes using tags.
This required quite a bit of refactoring. Added series_from_tag functions and corresponding tests, as well as series_from_branch input tests that test input conformance. Removed unnecessary CandidateRN, SnapshotRN, and ReleaseRN classes to shallow the topology.
-rw-r--r--linaropy/git/clone.py11
-rw-r--r--linaropy/git/gitrepo.py37
-rw-r--r--linaropy/rn/gccclone.py2
-rw-r--r--linaropy/rn/linaroseries.py14
-rw-r--r--linaropy/rn/rngen.py31
-rw-r--r--linaropy/rn/rnseries.py300
-rw-r--r--linaropy/rn/template.py56
-rw-r--r--linaropy/series.py205
-rw-r--r--rn.py90
-rwxr-xr-xtcwg-release.sh4
10 files changed, 483 insertions, 267 deletions
diff --git a/linaropy/git/clone.py b/linaropy/git/clone.py
index d8fe126..2fb3843 100644
--- a/linaropy/git/clone.py
+++ b/linaropy/git/clone.py
@@ -63,7 +63,9 @@ class Clone(GitRepo):
except ErrorReturnCode:
raise EnvironmentError('Specified clonedir is not a git repository.')
- # Strip off the directory name
+ # Strip off any trailing /
+ clonedir=clonedir.rstrip('/')
+ # We only want the final directory name, not the whole path.
clone_dirname=clonedir.rsplit('/', 1)[-1]
self.repodir=self.proj.projdir + '/' + clone_dirname
@@ -180,6 +182,13 @@ class TestClone(unittest.TestCase):
# Verify that a symlink is used for the clone.
self.assertTrue(os.path.islink(self.clone.clonedir()))
+ # This was a bug at some point, as it would strip off the repository name.
+ def test_existing_clonedir_with_trailing_slash(self):
+ self.clone=Clone(self.proj,clonedir=TestClone.rnclone.clonedir() + "/")
+
+ # Verify that a symlink is used for the clone.
+ self.assertTrue(os.path.islink(self.clone.clonedir()))
+
def test_failed_symlink(self):
# We'll make the projdir read-only so we can force symlink creation
# to fail.
diff --git a/linaropy/git/gitrepo.py b/linaropy/git/gitrepo.py
index 99b2573..b9f2c03 100644
--- a/linaropy/git/gitrepo.py
+++ b/linaropy/git/gitrepo.py
@@ -45,6 +45,7 @@ class GitRepo(object):
raise TypeError('proj input parameter is not of type Proj')
def branchexists(self, branch):
+ logging.info("Checking to see if branch %s exists" % branch)
with cd(self.repodir):
try:
# Quote the branchname because it might have strange
@@ -52,6 +53,7 @@ class GitRepo(object):
br="%s" % branch
git("rev-parse", "--verify", br)
except ErrorReturnCode_128:
+ logging.info("Couldn't find branch %s" % branch)
return False
return True
@@ -63,6 +65,11 @@ class GitRepo(object):
raise EnvironmentError("Unable to get the current branch")
return branch
+ # TODO make this a bit more sophisticated because the user might not be
+ # using 'origin' as their remote name.
+ def remote_branchname(self, branchname):
+ return "remotes/origin/" + branchname
+
# TODO: Fully test this.
# Stash current changes and change to new branch.
# Return to previous branch when context is exited.
@@ -125,18 +132,23 @@ class GitRepo(object):
# TODO: Write a unit test for this.
# TODO: fix the default
def commit(self, message="default"):
- print "Committing changes."
+ logging.info("Attempting to commit changes to %s" % self.repodir )
try:
with cd(self.repodir):
# Git commit first with a boiler plate message and then allow the user
# to amend.
if git("status", "--porcelain"):
- # print git("commit", "-m", '%s' % message, _err_to_out=True)
+ # using python sh will suppress the git editor
subprocess.call(["git", "commit", "-m", message])
- # using python sh will suppress the git editor
subprocess.call(["git", "commit", "--amend"])
+ else:
+ logging.info("Nothing to commit.")
+ return False
except ErrorReturnCode:
raise EnvironmentError("Unable to git commit ")
+ return False
+ # Something was committed.
+ return True
def log(self, number):
try:
@@ -146,7 +158,7 @@ class GitRepo(object):
raise EnvironmentError("Unable to git add " + filetogitadd)
# TODO: Does this need to 'cd' first?
- def editFile(self, toedit):
+ def edit(self, toedit):
editor = os.getenv('EDITOR')
if not editor:
editor='/usr/bin/vim'
@@ -169,6 +181,17 @@ class GitRepo(object):
except ErrorReturnCode:
raise EnvironmentError("Unable to push branch %s to %s" % (branch, tobranch))
+ def tag_exists(self, tag):
+ try:
+ with cd(self.repodir):
+ print("testing tag %s on repo %s" % (tag, self.repodir))
+ tagref="refs/tags/%s" % tag
+ git("rev-parse", "-q", "--verify", tagref)
+ except ErrorReturnCode_128:
+ logging.info("Couldn't find tag %s" % tag)
+ return False
+ return True
+
def __str__(self):
return self.repodir
@@ -212,8 +235,10 @@ class TestGitRepo(unittest.TestCase):
# TODO: Create a test-branch in the repo so it's always there.
- def test_branchexists(self):
- self.assertTrue(self.dgr.branchexists("remotes/origin/releases/linaro-4.9-2015.05"))
+ def test_tag_exists(self):
+ with cd(self.dgr.repodir):
+ git("tag", "-a", "linaro-99.9-2099.08-rc1", "-m", "This is a test tag")
+ self.assertTrue(self.dgr.tag_exists("linaro-99.9-2099.08-rc1"))
def test_not_branchexists(self):
self.assertFalse(self.dgr.branchexists("foobar"))
diff --git a/linaropy/rn/gccclone.py b/linaropy/rn/gccclone.py
index 36f610b..c6582f3 100644
--- a/linaropy/rn/gccclone.py
+++ b/linaropy/rn/gccclone.py
@@ -1,3 +1,4 @@
+import logging
from sh import git
from ..git.clone import Clone
@@ -7,6 +8,7 @@ class GCCClone(Clone):
def __init__(self, proj, clonedir=None, remote=None ):
super(GCCClone,self).__init__(proj, clonedir, remote)
+ logging.info("Changing directory to clonedir %s." % clonedir)
with cd(clonedir):
try:
with open('gcc/BASE-VER', 'r') as f:
diff --git a/linaropy/rn/linaroseries.py b/linaropy/rn/linaroseries.py
index f978655..b3e0322 100644
--- a/linaropy/rn/linaroseries.py
+++ b/linaropy/rn/linaroseries.py
@@ -1,12 +1,14 @@
import unittest
import copy
+import logging
from datetime import datetime
from dateutil.relativedelta import relativedelta
from ..vers import Spin
from ..vers import Rc
from ..series import Series
-from ..series import seriesFromBranchname
+from ..series import series_from_branchname
+from ..series import series_from_tag
# Progression:
# The Linaro release progression follows.
@@ -50,6 +52,7 @@ class LinaroSeries(Series):
super(LinaroSeries,self).__init__(seriestype, vendor, package, date,spin,rc, strict)
def toNextCandidate(self, date=None, strict=False):
+ logging.info('from %s toNextCandidate' % self.longlowertype())
if self.seriestype < 0 or self.seriestype >= len(Series.series):
raise TypeError('toNextCandidate on an unknown series type.')
@@ -91,6 +94,7 @@ class LinaroSeries(Series):
return candidate
def toNextRelease(self, date=None, strict=False):
+ logging.info('from %s toNextRelease' % self.longlowertype())
if self.seriestype < 0 or self.seriestype >= len(Series.series):
raise TypeError('toNextRelease called on an unknown series type.')
elif self.seriestype == Series.series.index("release"):
@@ -116,6 +120,7 @@ class LinaroSeries(Series):
return release
def toNextSnapshot(self, date=None, strict=False):
+ logging.info('from %s toNextSnapshot' % self.longlowertype())
if self.seriestype < 0 or self.seriestype >= len(Series.series):
raise TypeError('toNextRelease called on an unknown series type.')
elif self.seriestype == Series.series.index("candidate"):
@@ -146,6 +151,11 @@ class LinaroSeries(Series):
def toNext(self, seriestype, date=None, strict=False):
return self.dispatchnext[seriestype](date, strict)
+def linaro_series_from_tag(tag=None):
+ series=series_from_tag(tag)
+ linaroseries=LinaroSeries(Series.series[series.seriestype], vendor="linaro", package=series.package ,date=series.date , spin=series.spin, rc=series.rc, strict=True )
+ return linaroseries
+
# Helper function which creates a LinaroSeries from a properly formed branch name
# input string.
def linaroSeriesFromBranchname(branch=None):
@@ -153,7 +163,7 @@ def linaroSeriesFromBranchname(branch=None):
# Create a Series using the helper function and then populate a
# LinaroSeries. TODO: There's probably a better way to do this such
# as a SeriesFactory that is overridden.
- series=seriesFromBranchname(branch)
+ series=series_from_branchname(branch)
linaroseries=LinaroSeries(Series.series[series.seriestype], vendor="linaro", package=series.package ,date=series.date , spin=series.spin, rc=series.rc, strict=True )
return linaroseries
diff --git a/linaropy/rn/rngen.py b/linaropy/rn/rngen.py
index d418712..bfbb05b 100644
--- a/linaropy/rn/rngen.py
+++ b/linaropy/rn/rngen.py
@@ -32,7 +32,7 @@ import urllib2
from ..series import Series
from linaroseries import LinaroSeries
-from rnseries import CandidateRN
+from rnseries import RNSeries
from gccclone import GCCClone
from ..rninput import finput
@@ -42,11 +42,9 @@ def get_gcc_version(gccclone):
(dct["major"],dct["minor"],dct["revision"]) = gccclone.get_base_version().split(".")
return dct
-def rngen(candidate, gccclone):
- #TODO Test that candidate is a CandidateRN
-
- trackseries=candidate.get_track_series()
- nextseries=candidate.get_next_series()
+def rngen(rn_series, gccclone):
+ trackseries=rn_series.track_series
+ nextseries=rn_series.next_series
print "toNext: " + nextseries.getBranchname()
print "toNext: " + format(nextseries, '%N/%d')
@@ -80,7 +78,7 @@ def rngen(candidate, gccclone):
gcc_version_path=ver['major']
stab_maint='Stable'
- print "This is a %s candidate for GCC version %s" % (stab_maint,
+ print "This is a %s RNSeries for GCC version %s" % (stab_maint,
gcc_version_path)
history=finput('Please enter the location of the changelog csv file: ', "6.1-2016.06.csv")
@@ -113,8 +111,8 @@ def rngen(candidate, gccclone):
spin=str(nextseries.spin).strip('-')
rc=str(nextseries.rc).strip("-rc")
- template_dir=candidate.rntemplate.workdir()
- series_dir=candidate.rnworkdir.workdir()
+ template_dir=rn_series.rn_template.workdir()
+ series_dir=rn_series.rn_series.workdir()
# Verify that the basis url is actually valid, otherwise the release notes
# will contain erroneous information.
@@ -290,14 +288,7 @@ def rngen(candidate, gccclone):
copyfile(out_source + u'.textile' ,src_readme )
print 'Wrote generated file ' + out_source + u'.textile' + " to " + src_readme
- candidate.rnworkdir.add(bin_readme)
- candidate.rnworkdir.add(src_readme)
- candidate.rnworkdir.commit("Generated Release Notes for " + nextseries.label())
- candidate.rnworkdir.log(1)
-
- # TODO: Ask if the user would like to push the release notes changes.
-
- quit(0);
-
-if __name__ == "__main__":
- main(sys.argv[1:])
+ rn_series.rn_series.add(bin_readme)
+ rn_series.rn_series.add(src_readme)
+ rn_series.rn_series.commit("Generated Release Notes for %s." % nextseries.label())
+ rn_series.rn_series.log(1)
diff --git a/linaropy/rn/rnseries.py b/linaropy/rn/rnseries.py
index d3e2c3f..284e6d9 100644
--- a/linaropy/rn/rnseries.py
+++ b/linaropy/rn/rnseries.py
@@ -10,10 +10,9 @@ from ..git.gitrepo import cd
from ..git.clone import Clone
from ..git.workdir import Workdir
from ..series import Series
-from ..series import seriesFromBranchname
from linaroseries import LinaroSeries
from linaroseries import linaroSeriesFromBranchname
-from template import TemplateRN
+from template import RNTemplate
from ..rninput import yninput
@@ -27,10 +26,10 @@ class RNSeries(object):
_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.
- # @trackseries - an instance of a LinaroSeries to track.
- # @nextseries - an instance of a LinaroSeries that is the next series.
- def __init__(self, proj, rnrepo=None, trackseries=None, nextseries=None, headless=False):
-
+ # @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
@@ -38,156 +37,167 @@ class RNSeries(object):
if rnrepo:
logging.info('RNSeries() clone already exists. Using existing.')
- self.rnclone=Clone(proj, clonedir=rnrepo)
+ self.rn_clone=Clone(proj, clonedir=rnrepo)
else:
- self.rnclone=Clone(proj, remote=RNSeries.rnremote)
+ self.rn_clone=Clone(proj, remote=RNSeries.rnremote)
# TODO: Write a testcase that exposes this.
- if not trackseries:
- raise TypeError("Input variable trackseries is required.")
+ if not track_series:
+ raise TypeError("Input variable track_series is required.")
# TODO: Write a testcase that exposes this.
- if not isinstance(trackseries, LinaroSeries):
- raise TypeError("Input variable trackseries not of type Series.")
+ 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 nextseries:
- raise TypeError("Input variable nextseries is required.")
+ if not next_series:
+ raise TypeError("Input variable next_series is required.")
# TODO: Write a testcase that exposes this.
- if not isinstance(nextseries, LinaroSeries):
- raise TypeError("Input variable nextseries not of type Series.")
-
- self.trackseries=trackseries
- self.nextseries=nextseries
-
- self.proj=proj
-
- templ_branchname=self.nextseries.shorttype() + "_" + self.nextseries.getDir()
-
- logging.info('RNSeries() Creating TemplateRN')
- # Every release-notes series contains a 'template' workdir checked out
- # into a new templ_branchname branch that tracks master.
- self.rntemplate=TemplateRN(self.proj,self.rnclone, branchname_suffix=templ_branchname)
-
- # We do this now because the SeriesRN workdir might be branched from the template.
- self.rntemplate.updateTemplateReadme()
- updateseries=self.rntemplate.updateTemplateSeries()
-
- self.rntemplate.commit()
-
- print "Please verify that your changes have been committed on the template branch."
- self.rntemplate.log(1)
-
- # It's possible that self.trackseries.getBranchname() doesn't exist
- # (such is the case if we're creating the first candidate from a
- # snapshot). In this case 'track' should be the local template branch
- # so that we pick up the template changes.
- if not self.rntemplate.branchexists(self.trackseries.getBranchname()):
- print("Creating RNSeries based on branch " + self.rntemplate.getbranch())
- self.rnworkdir=Workdir(proj=self.proj, clone=self.rnclone, workdir=self.nextseries.shorttype(), track=self.rntemplate.getbranch(), branchname=self.nextseries.getBranchname())
- else:
- print "You updated the template README.textile.series but this will not be reflected in the Candidate README.textile.series."
- print "Creating RNSeries based on branch " + self.trackseries.getBranchname()
- self.rnworkdir=Workdir(proj=self.proj, clone=self.rnclone, workdir=self.nextseries.shorttype(), track=self.trackseries.getBranchname(), branchname=self.nextseries.getBranchname())
-
- print "Log of last commit on workdir branch:"
- self.rnworkdir.log(1)
-
- print "If you would like to make changes to the series release notes please update the the Candidate README.textile.series file:"
- answer=yninput("Do you need to update the Candidate README.textile.series file?", "N")
- if answer == "y":
- self.rnworkdir.editFile(self._series)
- else:
- print "The Candidate README.textile.series file has not been updated."
-
- self.rnworkdir.commit()
-
- print "Log of last commit on workdir branch:"
- self.rnworkdir.log(1)
-
+ 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.getDir()
+ 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.getBranchname())
+ if not self.rn_series:
+ print("Looking for branch %s" % self.track_series.getBranchname())
+ # 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.getBranchname()):
+ 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.getBranchname())
+ else:
+ logging.info(
+ "MARK Creating RNSeries based on branch "
+ + remote_track)
+ # + self.track_series.getBranchname())
+
+ self.rn_series=Workdir(
+ proj=self.proj,
+ clone=self.rn_clone,
+ workdir=self.next_series.shorttype(),
+ track=remote_track,
+ branchname=self.next_series.getBranchname())
+ #track=self.track_series.getBranchname(),
+
+ 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.getBranchname())
+
+ # 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.getBranchname())
+
+ def push_readme_updates(self):
+ pass
# TODO: Don't forget to push template and workdir changes.
- # self.rntemplate.pushToBranch("origin/master")
+ # self.rn_template.pushToBranch("origin/master")
# TODO: Should the workdir know where to push to?
- # self.rnworkdir.pushToBranch(self.nextseries.getBranchname())
-
- def get_next_series(self):
- return self.nextseries
-
- def get_track_series(self):
- return self.trackseries
-
-# Do we even need these, especially if they're all the same?
-class SnapshotRN(RNSeries):
- def __init__(self, proj, trackseries, rnrepo=None):
- if not isinstance(trackseries, LinaroSeries):
- raise TypeError('The series input must be of type LinaroSeries')
-
- nextseries=trackseries.toNextSnapshot(strict=True)
-
- super(SnapshotRN,self).__init__(proj, rnrepo, trackseries=trackseries, nextseries=nextseries)
-
-class CandidateRN(RNSeries):
- def __init__(self, proj, trackseries, rnrepo=None):
- if not isinstance(trackseries, LinaroSeries):
- raise TypeError('The trackseries input must be of type LinaroSeries')
-
- self.nextseries=trackseries.toNextCandidate(strict=True)
-
- super(CandidateRN,self).__init__(proj, rnrepo, trackseries=trackseries, nextseries=self.nextseries)
-
-class ReleaseRN(RNSeries):
- def __init__(self, proj, trackseries, rnrepo=None):
- if not isinstance(trackseries, LinaroSeries):
- raise TypeError('The series input must be of type LinaroSeries')
-
- nextseries=trackseries.toNextRelease(strict=True)
-
- super(ReleaseRN,self).__init__(proj, rnrepo, trackseries=trackseries, nextseries=nextseries)
-
-class TestCandidateRN(unittest.TestCase):
- #logging.basicConfig(level="INFO")
- testdirprefix="CandidateRNUT"
-
- @classmethod
- def setUpClass(cls):
- cls.proj=Proj(prefix=TestCandidateRN.testdirprefix, persist=True)
- logging.info('11111 Created Proj dir')
- cls.rnrepo=Clone(cls.proj,remote=u'http://git.linaro.org/toolchain/release-notes.git')
- logging.info('22222 Created clone dir')
- cls.branch=u'snapshots/linaro-6.1-2016.06'
- cls.series=linaroSeriesFromBranchname(branch=cls.branch)
-
- @classmethod
- def tearDownClass(cls):
- cls.proj.cleanup()
-
- def test_candidate_newclone(self):
- logging.info('33333 Going To Create CandidateRN')
- candidatern=CandidateRN(self.proj, rnrepo=self.rnrepo.repodir, trackseries=self.series)
- logging.info('44444 Created CandidateRN')
- self.assertEqual(candidatern.nextseries.longuppertype(), "Release-Candidate")
- self.assertEqual(candidatern.nextseries.longlowertype(), "release-candidate")
- self.assertTrue(os.path.isdir(self.proj.projdir + "/release-notes.git"))
- self.assertTrue(os.path.isdir(self.proj.projdir + "/candidate"))
- self.assertTrue(os.path.isdir(self.proj.projdir + "/template"))
-
-# def test_candidate_existingclone(self):
-# # Since this reuses an existing clone of a repository the
-# # release-notes.git directory should actually be a symlink.
-# candidatern=CandidateRN(self.proj, trackseries=self.series, rnrepo=TestCandidateRN.rnrepo.repodir)
-# self.assertEqual(candidatern.series.longuppertype(), "Release-Candidate")
-# self.assertEqual(candidatern.series.longlowertype(), "release-candidate")
-# self.assertTrue(os.path.islink(self.proj.projdir + "/release-notes.git"))
-# self.assertTrue(os.path.isdir(self.proj.projdir + "/candidate"))
-# self.assertTrue(os.path.isdir(self.proj.projdir + "/template"))
-#
-# self.assertEqual(candidatern.rntemplate.getbranch().split("_")[0], "template")
-## self.assertTrue(candidatern.rnworkdir.getbranch().startswith("releases/"))
-#
-# print "Based on: %s" % self.series.getBranchname()
-# print "Template Branch: %s" % candidatern.rntemplate.getbranch()
-# print "Candidate Branch: %s" % candidatern.rnworkdir.getbranch()
+ # self.rn_series.pushToBranch(self.next_series.getBranchname())
+
+class TestSeriesRN(unittest.TestCase):
+ pass
if __name__ == '__main__':
+ logging.basicConfig(level="INFO")
unittest.main()
diff --git a/linaropy/rn/template.py b/linaropy/rn/template.py
index c036add..b5d0f59 100644
--- a/linaropy/rn/template.py
+++ b/linaropy/rn/template.py
@@ -10,7 +10,7 @@ from ..git.clone import Clone
from ..git.workdir import Workdir
from ..rninput import yninput
-class TemplateRN(Workdir):
+class RNTemplate(Workdir):
_readme='components/toolchain/binaries/README.textile'
_series='components/toolchain/binaries/README.textile.series'
@@ -19,13 +19,17 @@ class TemplateRN(Workdir):
branchname='template_' + branchname_suffix
else:
branchname='template_' + str(uuid.uuid4())
- super(TemplateRN, self).__init__(proj, rnclone, "template", track="origin/master", branchname=branchname)
+ super(RNTemplate, self).__init__(proj, rnclone, "template", track="origin/master", branchname=branchname)
# Todo move template workdir out of detached head state.
# TODO: Allow the user to edit BOTH the gcc-linaro/ and binaries/
# README.textile file as currently this function only does the binary one.
# TODO: Create Unit Test
- def updateTemplateReadme(self):
+ # TODO: test headless
+ def update_readme(self, headless=False):
+ if headless:
+ return False
+
answer=yninput("Would you like to update the Template README.textile file?", "N")
if answer != "y":
print "The Template README.textile file has not been updated."
@@ -35,13 +39,17 @@ class TemplateRN(Workdir):
if not editor:
editor='/usr/bin/vim'
print "Edit the README.textile template fragment if changes are needed."
- os.system(editor + ' ' + self.repodir + '/' + TemplateRN._readme)
+ os.system(editor + ' ' + self.repodir + '/' + RNTemplate._readme)
- self.add(TemplateRN._readme)
+ self.add(RNTemplate._readme)
return True
# TODO: Create Unit Test
- def updateTemplateSeries(self):
+ # TODO: test headless
+ def update_series(self, headless=False):
+ if headless:
+ return False
+
answer=yninput("Would you like to update the Template README.textile.series file?", "N")
if answer != "y":
print "The Template README.textile.series file has not been updated."
@@ -51,40 +59,42 @@ class TemplateRN(Workdir):
if not editor:
editor='/usr/bin/vim'
print "Edit the README.textile.series template fragment if changes are needed."
- os.system(editor + ' ' + self.repodir + '/' + TemplateRN._series)
+ os.system(editor + ' ' + self.repodir + '/' + RNTemplate._series)
- self.add(TemplateRN._series)
+ self.add(RNTemplate._series)
return True
- def getReadme(self):
- return self.repodir + '/' + TemplateRN._readme
+ # TODO: Do we need this?
+ def get_readme(self):
+ return self.repodir + '/' + RNTemplate._readme
- def getSeries(self):
- return self.repodir + '/' + TemplateRN._series
+ # TODO: Do we need this?
+ def get_series(self):
+ return self.repodir + '/' + RNTemplate._series
-class TestTemplateRN(unittest.TestCase):
- testdirprefix="TemplateRNUT"
+class TestRNTemplate(unittest.TestCase):
+ testdirprefix="RNTemplateUT"
# Every instance of TestClass requires its own proj directory.
def setUp(self):
- self.proj=Proj(prefix=TestTemplateRN.testdirprefix, persist=True)
+ self.proj=Proj(prefix=TestRNTemplate.testdirprefix, persist=True)
def tearDown(self):
self.proj.cleanup()
def test_getREADME(self):
self.rnrepo=Clone(self.proj,remote=u'http://git.linaro.org/toolchain/release-notes.git')
- self.rntemplate=TemplateRN(self.proj,self.rnrepo)
- compare=self.proj.projdir + '/template/' + TemplateRN._readme
- self.assertEqual(self.rntemplate.getReadme(),compare)
- self.assertTrue(os.path.isfile(self.rntemplate.getReadme()))
+ self.rn_template=RNTemplate(self.proj,self.rnrepo)
+ compare=self.proj.projdir + '/template/' + RNTemplate._readme
+ self.assertEqual(self.rn_template.get_readme(),compare)
+ self.assertTrue(os.path.isfile(self.rn_template.get_readme()))
def test_getSERIES(self):
self.rnrepo=Clone(self.proj,remote=u'http://git.linaro.org/toolchain/release-notes.git')
- self.rntemplate=TemplateRN(self.proj,self.rnrepo)
- compare=self.proj.projdir + '/template/' + TemplateRN._series
- self.assertEqual(self.rntemplate.getSeries(),compare)
- self.assertTrue(os.path.isfile(self.rntemplate.getSeries()))
+ self.rn_template=RNTemplate(self.proj,self.rnrepo)
+ compare=self.proj.projdir + '/template/' + RNTemplate._series
+ self.assertEqual(self.rn_template.get_series(),compare)
+ self.assertTrue(os.path.isfile(self.rn_template.get_series()))
# TODO: Test branchname_suffix
diff --git a/linaropy/series.py b/linaropy/series.py
index 3e6830c..cad1e31 100644
--- a/linaropy/series.py
+++ b/linaropy/series.py
@@ -2,6 +2,7 @@ import unittest
import logging
import os
import uuid
+import string
from vers import Spin
from vers import Rc
@@ -146,8 +147,9 @@ class Series(object):
'%R': self._getRc,
}
+
def _getPackageName(self):
- return self.package.pv
+ return self.package.package
def _getPackageNameLower(self):
return self.package.lower()
@@ -174,7 +176,6 @@ class Series(object):
ret=''
# Iterate across the dictionary and for each key found and invoke the
# function.
- import string
ret=format_spec
for key in self.fmt.iterkeys():
replac=self.fmt[key]()
@@ -239,7 +240,7 @@ class Series(object):
return branchname
-def seriesFromBranchname(branch=None):
+def series_from_branchname(branch=None):
"""
Create a Series from a branch name string.
@@ -264,30 +265,36 @@ def seriesFromBranchname(branch=None):
-------
releases/<foo>[!-rcN]
"""
+ logging.info("Branch is %s." % branch)
if not isinstance(branch, basestring):
- raise TypeError('seriesFromBranchname requires a basestring as input')
+ raise TypeError('series_from_branchname requires a basestring as input')
if not branch:
- raise ValueError('seriesFromBranchname requires a non-empty string as input')
+ raise TypeError('series_from_branchname requires a non-empty string as input')
# Get the part before the '/'. That's the namespace
try:
namespace=branch.rsplit('/', 1)[0]
except IndexError:
- raise RuntimeError('string must be <namespace>/<everything_else>')
+ raise ValueError('string must have a namespace, e.g., <namespace>/<everything_else>')
# Get everything after the '/'.
try:
seriesstr=branch.rsplit('/', 1)[1]
except IndexError:
- raise RuntimeError('string must be <package_name>-<package_version>')
+ raise ValueError("string must delimit the namespace from the right branch with a '/' char, e.g., <namespace>/<package_name>-<package_version>")
- if namespace == u'':
- raise TypeError("Couldn't parse a namespace from input string")
+ # TODO: Are these necessary or did the previous cases cover it?
+ #if namespace == u'':
+ # raise ValueError("Couldn't parse a namespace from input string")
+ # This will catch where there's a namespace/ but no right hand value after
+ # the /.
if seriesstr == u'':
- raise TypeError("Couldn't parse a series from input string")
+ raise ValueError("Couldn't parse a series from input string. Missing a branch name.")
keys=['vendor', 'version', 'date', 'spin', 'rc']
+ # This might generate key errors, depending on whether anything can be
+ # parsed from the right-hand values.
values=seriesstr.split('-')
dictionary=dict(zip(keys, values))
@@ -306,11 +313,16 @@ def seriesFromBranchname(branch=None):
# strip the "rc" and just leave the int.
if dictionary["rc"].startswith("rc"):
dictionary["rc"]=dictionary["rc"][2:]
+ if not dictionary["rc"].isnumeric():
+ raise TypeError("The rc value must be numeric.")
# We need to have None fields in the missing keys for when we call the
# Series constructor.
if not dictionary.has_key("spin"):
dictionary["spin"]=None
+ else:
+ if not dictionary["spin"].isnumeric():
+ raise TypeError("The spin must be numeric.")
seriesdate=datetime.today
if dictionary["date"]:
@@ -322,9 +334,9 @@ def seriesFromBranchname(branch=None):
seriesdate=datetime(int(datefields["year"]), int(datefields["month"]), int(datefields["day"]))
if "snapshots" in namespace and dictionary["rc"]:
- raise RuntimeError('A snapshots namespace can not have an rc. This is a non-conforming input.')
+ raise ValueError('A snapshots namespace can not have an rc. This is a non-conforming input.')
elif "releases" not in namespace and dictionary["rc"]:
- raise RuntimeError('An rc must have a "releases" namespace. This is a non-conforming input.')
+ raise ValueError('An rc must have a "releases" namespace. This is a non-conforming input.')
elif dictionary["rc"]:
seriesname="candidate"
elif "snapshots" in namespace:
@@ -332,16 +344,65 @@ def seriesFromBranchname(branch=None):
elif "releases" in namespace:
seriesname="release"
elif "snapshot" in namespace:
- raise RuntimeError('"snapshot" is not a complete namespace. A conforming namespace is "snapshots".')
+ raise ValueError('"snapshot" is not a complete namespace. The conforming namespace is "snapshots".')
else:
# TODO test for unknown namespace.
- raise RuntimeError('Unknown namespace in input string.')
+ raise ValueError('Unknown namespace in input string.')
package=Package(package="GCC", version=dictionary["version"])
series=Series(seriesname, package=package, date=seriesdate, spin=dictionary["spin"], rc=dictionary["rc"], strict=True)
return series
+def series_from_tag(tag=None):
+ """
+ Create a Series from a git tag name
+
+ Parameters
+ ----------
+ tag : str
+
+ The git tag of a package as it lives in a git repository. A properly
+ formed tag will take the following form:
+
+ Snapshot
+ --------
+ linaro-snapshot-Maj.min-YYYY.MM[-spin]
+
+ Candidate
+ ---------
+ linaro-Maj.min-YYYY.MM[-spin]-rcN
+
+ Release
+ -------
+ linaro-Maj.min-YYYY.MM[-spin]
+ """
+
+ # TODO Test this.
+ if not tag:
+ raise ValueError('series_from_tag requires a tag')
+
+ # TODO Test this.
+ if not isinstance(tag, basestring):
+ raise TypeError('series_from_tag requires a basestring as input')
+
+ # This is default, we'll replace with 'snapshots' if we detect that the
+ # tag is indeed a snapshot.
+ namespace="releases"
+
+ # since 'snapshots' tags aren't the same as release and rc tags we need
+ # to force conformance, i.e., remove "-snapshot", but record the
+ # namespace as snapshots while we're at it.
+ if "snapshot" in tag:
+ tag=string.replace(tag,"-snapshot",'')
+ namespace="snapshots"
+
+ # Now we're going to cheat and fabricate a false branchname.
+ branchname=namespace + '/' + tag
+
+ # ... in which case we can reuse this function.
+ return series_from_branchname(branchname)
+
from vers import versionFromStr
class TestSeries(unittest.TestCase):
@@ -544,55 +605,131 @@ class TestSeries(unittest.TestCase):
release=Series("release", package="GCC-5.3.1", date=datetime(2016,05,15), rc="1", strict=False)
self.assertEqual(release.getBranchname(), "releases/linaro-5.3-2016.05-rc1")
- # TODO: Test combinations of branch names with and without spins/rcs.
-
- # TODO: Test whether seriesFromBranchname can detect non-conforming branch names.
-
# These tests will verify that a branchname can be read, a series created,
# and then the same branch name recreated.
- def test_seriesFromBranchname(self):
- branch=u'snapshots/linaro-5.3-2016.05-6-rc1'
- with self.assertRaises(RuntimeError):
- series=seriesFromBranchname(branch=branch)
+ def test_series_from_branchname(self):
branch2=u'snapshots/linaro-5.3-2016.05-6'
- series2=seriesFromBranchname(branch=branch2)
+ series2=series_from_branchname(branch=branch2)
self.assertEqual(series2.getBranchname(),u'snapshots/linaro-5.3-2016.05-6')
branch3=u'snapshots/linaro-5.3-2016.05'
- series3=seriesFromBranchname(branch=branch3)
+ series3=series_from_branchname(branch=branch3)
self.assertEqual(series3.getBranchname(),u'snapshots/linaro-5.3-2016.05')
branch4=u'releases/linaro-5.3-2016.05-6-rc1'
- series4=seriesFromBranchname(branch=branch4)
+ series4=series_from_branchname(branch=branch4)
self.assertEqual(series4.getBranchname(),u'releases/linaro-5.3-2016.05-6-rc1')
branch5=u'releases/linaro-5.3-2016.05-rc1'
- series5=seriesFromBranchname(branch=branch5)
+ series5=series_from_branchname(branch=branch5)
self.assertEqual(series5.getBranchname(),u'releases/linaro-5.3-2016.05-rc1')
branch6=u'releases/linaro-5.3-2016.05-6'
- series6=seriesFromBranchname(branch=branch6)
+ series6=series_from_branchname(branch=branch6)
self.assertEqual(series6.getBranchname(),u'releases/linaro-5.3-2016.05-6')
branch7=u'releases/linaro-5.3-2016.05'
- series7=seriesFromBranchname(branch=branch7)
+ series7=series_from_branchname(branch=branch7)
self.assertEqual(series7.getBranchname(),u'releases/linaro-5.3-2016.05')
+ # -rc1 is invalid with a snapshots namespace.
branch8=u'snapshots/linaro-5.3-2016.05-6-rc1'
- with self.assertRaises(RuntimeError):
- series8=seriesFromBranchname(branch=branch8)
+ with self.assertRaises(ValueError):
+ series8=series_from_branchname(branch=branch8)
+ # Wrong branchname.. it should be 'snapshots'
branch9=u'snapshot/linaro-5.3-2016.05-6-rc1'
- with self.assertRaises(RuntimeError):
- series9=seriesFromBranchname(branch=branch9)
+ with self.assertRaises(ValueError):
+ series9=series_from_branchname(branch=branch9)
+ # Wrong branchname.. it should be 'snapshots'
branch10=u'snapshot/linaro-5.3-2016.05-6'
- with self.assertRaises(RuntimeError):
- series10=seriesFromBranchname(branch=branch10)
+ with self.assertRaises(ValueError):
+ series10=series_from_branchname(branch=branch10)
+
+ # namespace required.
+ branch11=u'linaro-5.3-2016.05-6'
+ with self.assertRaises(ValueError):
+ series11=series_from_branchname(branch=branch11)
+
+ # it should complain about missing the right-hand values.
+ branch12=u'snapshots/'
+ with self.assertRaises(ValueError):
+ series12=series_from_branchname(branch=branch12)
+
+ # It won't parse because of a missing namespace /
+ branch13=u'snapshots'
+ with self.assertRaises(ValueError):
+ series13=series_from_branchname(branch=branch13)
+
+ branch14=u'snapshots/foo'
+ with self.assertRaises(KeyError):
+ series14=series_from_branchname(branch=branch14)
+
+ # unknown namespace.
+ branch15=u'foobarnamespace/linaro-5.3-2016.05-6'
+ with self.assertRaises(ValueError):
+ series15=series_from_branchname(branch=branch15)
+
+ # This will fail on a non-datetime input.
+ branch16=u'snapshots/linaro-5.3-asdf'
+ with self.assertRaises(ValueError):
+ series16=series_from_branchname(branch=branch16)
+
+ # This will fail with an invalid spin.
+ branch17=u'snapshots/linaro-5.3-2016.05-a'
+ with self.assertRaises(TypeError):
+ series17=series_from_branchname(branch=branch17)
+
+ # This will fail with an invalid rc.
+ branch18=u'snapshots/linaro-5.3-2016.05-rcasdfn'
+ with self.assertRaises(TypeError):
+ series18=series_from_branchname(branch=branch18)
+
+ # This will fail with an invalid rc.
+ branch19=u'snapshots/linaro-5.3-2016.05-9-rcasdfn'
+ with self.assertRaises(TypeError):
+ series19=series_from_branchname(branch=branch19)
# TODO: Test series.label (as there was a runtime bug)
+ def test_snapshot_series_from_tag(self):
+ tag=u'linaro-snapshot-5.3-2016.05-6'
+ series=series_from_tag(tag=tag)
+ self.assertEqual(series.getBranchname(),u'snapshots/linaro-5.3-2016.05-6')
+
+ def test_invalid_snapshot_series_from_tag(self):
+ # We can't have -rc1 on a snapshot.
+ tag=u'linaro-snapshot-5.3-2016.05-6-rc1'
+ with self.assertRaises(ValueError):
+ series=series_from_tag(tag=tag)
+
+ def test_candidate_series_from_tag(self):
+ tag=u'linaro-5.3-2016.05-6-rc1'
+ series=series_from_tag(tag=tag)
+ self.assertEqual(series.getBranchname(),u'releases/linaro-5.3-2016.05-6-rc1')
+
+ def test_release_series_from_tag(self):
+ tag=u'linaro-5.3-2016.05-6'
+ series=series_from_tag(tag=tag)
+ self.assertEqual(series.getBranchname(),u'releases/linaro-5.3-2016.05-6')
+
+ def test_series_from_tag_invalid_spin(self):
+ tag=u'linaro-5.3-2016.05-abc'
+ with self.assertRaises(TypeError):
+ series=series_from_tag(tag=tag)
+
+ def test_series_from_tag_invalid_rc(self):
+ tag=u'linaro-5.3-2016.05-rcabf'
+ with self.assertRaises(TypeError):
+ series=series_from_tag(tag=tag)
+
+ def test_series_from_tag_invalid_rc_with_valid_spin(self):
+ tag=u'linaro-5.3-2016.05-9-rcabf'
+ with self.assertRaises(TypeError):
+ series=series_from_tag(tag=tag)
+
if __name__ == '__main__':
#logging.basicConfig(level="INFO")
unittest.main()
diff --git a/rn.py b/rn.py
index aa88e81..ba6caac 100644
--- a/rn.py
+++ b/rn.py
@@ -16,11 +16,13 @@ from linaropy.rn.gccclone import GCCClone
from linaropy.git.clone import Clone
from linaropy.rn.linaroseries import LinaroSeries
from linaropy.rn.linaroseries import linaroSeriesFromBranchname
+from linaropy.rn.linaroseries import linaro_series_from_tag
from linaropy.proj import Proj
from linaropy.git.gitrepo import cd
-from linaropy.rn.template import TemplateRN
-from linaropy.rn.rnseries import CandidateRN
+from linaropy.rn.template import RNTemplate
+from linaropy.rn.rnseries import RNSeries
from linaropy.rn.rngen import rngen
+from linaropy.rninput import yninput
rnProj=[]
@@ -30,16 +32,16 @@ def rncleanup():
# This will be the case if the script is run via the test driver.
print "No cleanup needed"
else:
+ print "Cleaning up Proj dir %s if possible." % rnProj[0].projdir
rnProj[0].cleanup()
-def generate(track, todate, toseries, gccsource, persist):
+def generate(track, to_date, to_series, gccsource, persist):
# Delay creating the Proj directory until now so that the parser (and
# parser validation functions) can be tested in the unittests without
# invoking the internals of this driver.
rnProj.append(Proj(prefix='rn', persist=persist))
print "proj dir is: %s with persist=%s" % (rnProj[0].projdir, str(persist))
-
# This will raise an exception if gccsource is not a git repository.
gccclone=GCCClone(rnProj[0], clonedir=gccsource)
@@ -47,36 +49,54 @@ def generate(track, todate, toseries, gccsource, persist):
print 'gccbaseversion is ' + gccclone.get_base_version()
print 'fsf revision is ' + gccclone.get_fsf_revision()
- trackSeries=linaroSeriesFromBranchname(track)
-
- #rnclone=Clone(rnProj[0], remote=u'http://git.linaro.org/toolchain/release-notes.git')
- rnclone=Clone(rnProj[0], remote=u'ssh://git@git.linaro.org/toolchain/release-notes.git')
-
- # TODO: Check toseries to create the right *RN object.
- nexRN=CandidateRN(rnProj[0], rnrepo=rnclone.clonedir(), trackseries=trackSeries)
+ if gccclone.tag_exists(track):
+ logging.info("%s is a tag. Creating Series from tag.")
+ track_series=linaro_series_from_tag(track)
+ else:
+ logging.info("%s is a branch? Creating Series from branchname.")
+ track_series=linaroSeriesFromBranchname(track)
+
+ try:
+ next_series=track_series.toNext(to_series)
+ except TypeError:
+ print(
+ "Next series '%s' from '%s' in an invalid progression"
+ % (LinaroSeries.series[to_series], track_series.shorttype()))
+ print("If this is a release series try tracking the release-candidate tag instead of the release branch.")
+ sys.exit(2)
+
+ if to_date != next_series.date:
+ raise RuntimeError('The date passed to this driver does not equal the date computed by LinaroSeries.toNext()')
- nextSeries=nexRN.get_next_series()
+ rnclone=Clone(
+ rnProj[0],
+ remote=u'ssh://git@git.linaro.org/toolchain/release-notes.git')
- if todate != nextSeries.date:
- raise RuntimeError('The date passed to this driver does not equal the date computed by LinaroSeries.toNext()')
-# print "toNext: " + nextSeries.getBranchname()
-# print "toNext: " + format(nextSeries, '%N/%d')
+ next_rn=RNSeries(
+ rnProj[0],
+ rnrepo=rnclone.clonedir(),
+ track_series=track_series,
+ next_series=next_series)
- # TODO: What if 'track' is not a snapshot branch? To do this right we'd
- # probably have to preserve basedon information in the release notes
- # repository as a yaml file.
-# basedon='http://snapshots.linaro.org/components/toolchain/gcc-linaro/'
-# basedon=basedon + trackSeries.getDir()
-# print "basedon: " + basedon
+ if next_rn.update_templ_readmes():
+ print "Please verify that your changes have been committed on the template branch:"
+ self.rn_template.log(1)
- rngen(nexRN, gccclone)
+ ans="y"
+ while not ans=="n":
+ if next_rn.update_series_readmes():
+ print "Please verify that your changes have been committed on the series branch:"
+ next_rn.rn_series.log(1)
-# print 'gccbaseversion is ' + gccclone.get_base_version()
-# print 'fsf revision is ' + gccclone.get_fsf_revision()
+ # Generate the temporary output files to the projdir.
+ with cd(rnProj[0].projdir):
+ rngen(next_rn, gccclone)
- # TODO: After the release notes are generated, the generated files need
- # to be added, commit, and pushed.
- # These changes are on the CandidateRN workdir branch.
+ print "Please direct your browser to the rendered .html files in"
+ print "%s and make sure that they look correct." % rnProj[0].projdir
+ print "Would you like to edit the series README.textile.series file"
+ ans=yninput(
+ "again and regenerate the release notes?", "N")
# Verify that the GCC Source is located where it says it is.
class VerifyGCCSourceAction(argparse.Action):
@@ -111,28 +131,28 @@ def create_parser():
)
# Positionals are required by default.
- parser.add_argument('track', help='branchname of series to track.')
+ parser.add_argument('track', help='branchname or tag name of series to track.')
parser.add_argument('-g', '--gccsource', dest='gccsource', required=True, action=VerifyGCCSourceAction, help='location of the gcc source')
- parser.add_argument('-d', '--date', dest='todate', required=True, help='the next series date in "YYYY.MM" form.', type=str_to_datetime)
+ parser.add_argument('-d', '--date', dest='to_date', required=True, help='the next series date in "YYYY.MM" form.', type=str_to_datetime)
parser.add_argument('-n', '--nopersist', dest='persist', default=True, action='store_false', help='The proj dir will not persist once this program has executed.')
# At least one of the following arguments are required.
group = parser.add_mutually_exclusive_group(required=True)
- group.add_argument('-c', '--candidate', dest='toseries', action='store_const', const=LinaroSeries.series.index("candidate"))
- group.add_argument('-r', '--release', dest='toseries', action='store_const', const=LinaroSeries.series.index("release"))
- group.add_argument('-s', '--snapshot', dest='toseries', action='store_const', const=LinaroSeries.series.index("snapshot"))
+ group.add_argument('-c', '--candidate', dest='to_series', action='store_const', const=LinaroSeries.series.index("candidate"))
+ group.add_argument('-r', '--release', dest='to_series', action='store_const', const=LinaroSeries.series.index("release"))
+ group.add_argument('-s', '--snapshot', dest='to_series', action='store_const', const=LinaroSeries.series.index("snapshot"))
return parser
def main():
parser=create_parser()
args = parser.parse_args()
- generate(args.track, args.todate, args.toseries, args.gccsource, args.persist)
+ generate(args.track, args.to_date, args.to_series, args.gccsource, args.persist)
if __name__ == '__main__':
-# logging.basicConfig(level="INFO")
+ logging.basicConfig(level="INFO")
with handle_exit(rncleanup):
main()
diff --git a/tcwg-release.sh b/tcwg-release.sh
index 73dfb97..495ef0b 100755
--- a/tcwg-release.sh
+++ b/tcwg-release.sh
@@ -937,8 +937,10 @@ mydir="$(dirname "$(readlink -f "$0")")"
print_info "${bold}Generating release notes into ${REL_DIR}/git/"
+next_series="${SNAPSHOT:+-s}${RELEASE:+-r}${CANDIDATE:+-c}"
+
set -x
- python ${mydir}/rn.py ${track} -c -g ${REL_DIR}/git --date ${DATE}
+ python ${mydir}/rn.py ${track} ${next_series} -g ${REL_DIR}/git --date ${DATE}
set +x
popd 1>/dev/null