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
|
# Software License Agreement (BSD License)
#
# Copyright (c) 2013, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import print_function
import traceback
from bloom.generators import BloomGenerator
from bloom.git import inbranch
from bloom.git import get_current_branch
from bloom.logging import debug
from bloom.logging import error
from bloom.logging import fmt
from bloom.logging import info
from bloom.logging import warning
from bloom.packages import get_package_data
from bloom.util import execute_command
from bloom.commands.git.patch.trim_cmd import trim
try:
import catkin_pkg
from packaging.version import parse as parse_version
if parse_version(catkin_pkg.__version__) < parse_version('0.3.8'):
warning("This version of bloom requires catkin_pkg version >= '0.3.8',"
" the used version of catkin_pkg is '{0}'".format(catkin_pkg.__version__))
from catkin_pkg import metapackage
except ImportError as err:
debug(traceback.format_exc())
error("catkin_pkg was not detected, please install it.", exit=True)
class ReleaseGenerator(BloomGenerator):
title = 'release'
description = """\
Generates a release branch for each of the packages in the source branch.
The common use case for this generator is to produce release/* branches for
each package in the upstream repository, so the source branch should be set to
'upstream' and the prefix set to 'release'.
"""
def prepare_arguments(self, parser):
# Add command line arguments for this generator
add = parser.add_argument
add('-s', '--src', '--source-branch', default=None, dest='src',
help="git branch to branch from (defaults to 'upstream')")
add('-n', '--package-name', default=None, dest='name',
help="name of package being released (use if non catkin project)")
add('-p', '--prefix', default='release', dest='prefix',
help="prefix for target branch name(s)")
add('--release-increment', '-i', default=0,
help="release increment number")
return BloomGenerator.prepare_arguments(self, parser)
def handle_arguments(self, args):
self.interactive = args.interactive
self.prefix = args.prefix
if args.src is None:
current_branch = get_current_branch()
if current_branch is None:
error("Could not determine current branch.", exit=True)
self.src = current_branch
else:
self.src = args.src
self.name = args.name
self.release_inc = args.release_increment
def summarize(self):
self.branch_list = self.detect_branches()
if type(self.branch_list) not in [list, tuple]:
self.exit(self.branch_list if self.branch_list is not None else 1)
info("Releasing package" +
('' if len(self.branch_list) == 1 else 's') + ": " + str(self.branch_list))
def get_branching_arguments(self):
p, s, i = self.prefix, self.src, self.interactive
self.branch_args = [['/'.join([p, b]), s, i] for b in self.branch_list]
return self.branch_args
def pre_rebase(self, destination, msg=None):
name = destination.split('/')[-1]
msg = msg if msg is not None else (
"Releasing package '" + name + "' to: '" + destination + "'"
)
info(msg)
ret = trim(undo=True)
return 0 if ret is None or ret < 0 else ret # Ret < 0 indicates nothing was done
def post_rebase(self, destination):
# Figure out the trim sub dir
name = destination.split('/')[-1]
trim_d = [k for k, v in self.packages.items() if v.name == name][0]
# Execute trim
if trim_d in ['', '.']:
return
return trim(trim_d)
def post_patch(self, destination):
# Figure out the version of the given package
if self.name is not None:
warning("""\
Cannot automatically tag the release because this is not a catkin project.""")
warning("""\
Please checkout the release branch and then create a tag manually with:""")
warning(" git checkout release/" + str(self.name))
warning(" git tag -f release/" + str(self.name) + "/<version>")
return
with inbranch(destination):
name, version, packages = get_package_data(destination)
# Execute git tag
release_tag = destination + '/' + version + '-' + self.release_inc
execute_command('git tag ' + release_tag)
def metapackage_check(self, path, pkg):
if pkg.is_metapackage():
try:
metapackage.validate_metapackage(path, pkg)
except metapackage.InvalidMetapackage as e:
warning("Invalid metapackage:")
warning(" %s\n" % str(e))
error(fmt("Refusing to release invalid metapackage '@|%s@{rf}@!', metapackage requirements:\n @|%s" %
(pkg.name, metapackage.DEFINITION_URL)), exit=True)
def detect_branches(self):
self.packages = None
with inbranch(self.src):
if self.name is not None:
self.packages = [self.name]
return [self.name]
name, version, packages = get_package_data(self.src)
self.packages = packages
# Check meta packages for valid CMakeLists.txt
if isinstance(self.packages, dict):
for path, pkg in self.packages.items():
# Check for valid CMakeLists.txt if a metapackage
self.metapackage_check(path, pkg)
return name if type(name) is list else [name]
|