def check_towncrier(data, check_sanity=True, do_draft=True): """Check if towncrier can and should be run. This is a zest.releaser entrypoint that is called during prerelease, postrelease, and bumpversion. Not in all cases are all checks useful, so there are some options. For example, postrelease should not complain that there are no news fragments. """ if TOWNCRIER_MARKER in data: # We have already been called. return data[TOWNCRIER_MARKER] if not data.get('update_history', True): # Someone has instructed zest.releaser to not update the history, # and it was not us, because our marker was not set, # so we should not update the history either. logger.debug( 'update_history is already False, so towncrier will not be run.') data[TOWNCRIER_MARKER] = False return False # Check if towncrier should be applied. result = _is_towncrier_wanted() if not result: logger.debug('towncrier is not wanted.') else: result = _towncrier_executable() if result: logger.debug('towncrier should be run.') # zest.releaser should not update the history. # towncrier will do that. data['update_history'] = False if check_sanity: _report_newsfragments_sanity() if do_draft: # Do a draft. cmd = deepcopy(result) cmd.extend([ '--draft', '--version', data.get('new_version', 't.b.d.'), '--yes', ]) # We would like to pass ['--package' 'package name'] as well, # but that is not yet in a release of towncrier. logger.info( 'Doing dry-run of towncrier to see what would be changed: %s', utils.format_command(cmd)) print(utils.execute_command(cmd)) else: print( dedent(""" According to the pyproject.toml file, towncrier is used to update the changelog. The problem is: we cannot find the towncrier executable. Please make sure it is on your PATH.""")) if not utils.ask('Do you want to continue anyway?', default=False): sys.exit(1) data[TOWNCRIER_MARKER] = result return result
def _diff_and_commit(self, commit_msg=''): """Show diff and offer commit. commit_msg is optional. If it is not there, we get the commit_msg from self.data. That is the usual mode and is at least used in prerelease and postrelease. If it is not there either, we ask. """ if not commit_msg: if 'commit_msg' not in self.data: # Ask until we get a non-empty commit message. while not commit_msg: commit_msg = utils.get_input( "What is the commit message? ") else: commit_msg = self.data['commit_msg'] diff_cmd = self.vcs.cmd_diff() diff = execute_command(diff_cmd) if sys.version.startswith('2.6.2'): # python2.6.2 bug... http://bugs.python.org/issue5170 This is the # spot it can surface as we show a part of the changelog which can # contain every kind of character. The rest is mostly ascii. print("Diff results:") print(diff) else: # Common case logger.info("The '%s':\n\n%s\n", utils.format_command(diff_cmd), diff) if utils.ask("OK to commit this"): msg = commit_msg % self.data msg = self.update_commit_message(msg) commit_cmd = self.vcs.cmd_commit(msg) commit = execute_command(commit_cmd) logger.info(commit)
def available_tags(self): base = self._base_from_svn() tags_name = self._tags_name if tags_name is None: # Suggest to create a tags dir with the default plural /tags name. print("tags dir does not exist at %s" % base + 'tags') if utils.ask("Shall I create it"): cmd = ['svn', 'mkdir', base + 'tags', '-m', "Creating tags directory."] logger.info("Running '%s'", utils.format_command(cmd)) print(execute_command(cmd)) tags_name = self._tags_name assert tags_name == 'tags' else: sys.exit(1) tag_info = execute_command( ['svn', 'list', '--non-interactive', base + tags_name]) network_errors = [ 'Could not resolve hostname', 'E670008', 'Repository moved', 'Unable to connect', ] found_errors = [1 for network_error in network_errors if network_error in tag_info] if found_errors: logger.error('Network problem: %s', tag_info) sys.exit(1) tags = [line.replace('/', '').strip() for line in tag_info.split('\n')] tags = [tag for tag in tags if tag] # filter empty ones logger.debug("Available tags: '%s'", ', '.join(tags)) return tags
def _info_if_tag_already_exists(self): if self.data['tag_already_exists']: # Safety feature. version = self.data['version'] tag = self.data['tag'] q = ("There is already a tag %s, show " "if there are differences?" % version) if utils.ask(q): diff_command = self.vcs.cmd_diff_last_commit_against_tag(tag) print(utils.format_command(diff_command)) print(execute_command(diff_command))
def _info_if_tag_already_exists(self): if self.data['tag_already_exists']: # Safety feature. version = self.data['version'] tag = self.data['tag'] q = ("There is already a tag %s, show " "if there are differences?" % version) if utils.ask(q): diff_command = self.vcs.cmd_diff_last_commit_against_tag(tag) print(utils.format_command(diff_command)) print(execute_command(diff_command))
def _check_if_tag_already_exists(self): """Check if tag already exists and show the difference if so""" version = self.data['version'] tag = self.data['tag'] if self.vcs.tag_exists(tag): self.data['tag_already_exists'] = True q = ("There is already a tag %s, show " "if there are differences?" % version) if utils.ask(q): diff_command = self.vcs.cmd_diff_last_commit_against_tag(tag) print(utils.format_command(diff_command)) print(execute_command(diff_command)) else: self.data['tag_already_exists'] = False
def main(): utils.configure_logging() vcs = zest.releaser.choose.version_control() if len(sys.argv) > 1: found = sys.argv[-1] else: found = utils.get_last_tag(vcs) name = vcs.name full_tag = vcs.tag_url(found) logger.debug("Picked tag %r for %s (currently at %r).", full_tag, name, vcs.version) logger.info("Showing log since tag %s and the last commit.", full_tag) log_command = vcs.cmd_log_since_tag(found) print(utils.format_command(log_command)) print(execute_command(log_command))
def call_towncrier(data): """Entrypoint: run towncrier when available and configured.""" # check_towncrier will either give a path to towncrier, or False. path = check_towncrier(data) if not path: return # path is a list cmd = deepcopy(path) cmd.extend(['--version', data['new_version'], '--yes']) # We would like to pass ['--package' 'package name'] as well, # but that is not yet in a release of towncrier. logger.info('Running command to update news: %s', utils.format_command(cmd)) print(utils.execute_command(cmd)) # towncrier stages the changes with git, # which BTW means that our plugin requires git. logger.info('The staged git changes are:') print(utils.execute_command(['git', 'diff', '--cached'])) logger.info('towncrier has finished updating the history file ' 'and has staged the above changes in git.')
def _make_tag(self): version = self.data['version'] tag = self.data['tag'] if self.data['tag_already_exists']: return cmds = self.vcs.cmd_create_tag(tag, self.data['tag-message'], self.data['tag-signing']) assert isinstance(cmds, (list, tuple)) # transitional guard if not isinstance(cmds[0], (list, tuple)): cmds = [cmds] if len(cmds) == 1: print("Tag needed to proceed, you can use the following command:") for cmd in cmds: print(utils.format_command(cmd)) if utils.ask("Run this command"): print(execute_command(cmd)) else: # all commands are needed in order to proceed normally print("Please create a tag %s for %s yourself and rerun." % (tag, version)) sys.exit(1) if not self.vcs.tag_exists(tag): print("\nFailed to create tag %s!" % (tag, )) sys.exit(1)
def available_tags(self): base = self._base_from_svn() tags_name = self._tags_name if tags_name is None: # Suggest to create a tags dir with the default plural /tags name. print("tags dir does not exist at %s" % base + 'tags') if utils.ask("Shall I create it"): cmd = [ 'svn', 'mkdir', base + 'tags', '-m', "Creating tags directory." ] logger.info("Running %r", utils.format_command(cmd)) print(execute_command(cmd)) tags_name = self._tags_name assert tags_name == 'tags' else: sys.exit(1) tag_info = execute_command( ['svn', 'list', '--non-interactive', base + tags_name]) network_errors = [ 'Could not resolve hostname', 'E670008', 'Repository moved', 'Unable to connect', ] found_errors = [ 1 for network_error in network_errors if network_error in tag_info ] if found_errors: logger.error('Network problem: %s', tag_info) sys.exit(1) tags = [line.replace('/', '').strip() for line in tag_info.split('\n')] tags = [tag for tag in tags if tag] # filter empty ones logger.debug("Available tags: %r", tags) return tags
def _make_tag(self): version = self.data['version'] tag = self.data['tag'] if self.data['tag_already_exists']: return cmds = self.vcs.cmd_create_tag(tag, self.data['tag-message'], self.data['tag-signing']) assert isinstance(cmds, (list, tuple)) # transitional guard if not isinstance(cmds[0], (list, tuple)): cmds = [cmds] if len(cmds) == 1: print("Tag needed to proceed, you can use the following command:") for cmd in cmds: print(utils.format_command(cmd)) if utils.ask("Run this command"): print(execute_command(cmd)) else: # all commands are needed in order to proceed normally print("Please create a tag %s for %s yourself and rerun." % (tag, version)) sys.exit(1) if not self.vcs.tag_exists(tag): print("\nFailed to create tag %s!" % (tag,)) sys.exit(1)