def test_get_specification(): spec = get_specification('something') assert not spec.valid spec = get_specification('http://spec.url') assert spec.scheme == u'http' spec = get_specification('https://spec.url') assert spec.scheme == u'https'
def cmd(verbose, revision_range): """ Verifies if the commit messages in a range of revisions have valid specifications. This command takes the same revision ranges as ``git log`` to specify which commits are processed When using the verbose mode merge commits are printed otherwise they are simply ignored """ repository = git.get_repository() if not repository: click.secho('This command must be executed inside a repository.', fg='red', bold=True) raise click.Abort commits = list(repository.iter_commits(revision_range)) invalid = 0 options = config.load_repository_configuration(repository.working_dir).get( 'specification', {}) allowed_schemes = options.get('allowed_schemes', ['https', 'offline']) allowed_formats = options.get('allowed_formats', {'uri'}) for commit in commits: is_a_merge = len(commit.parents) > 1 if is_a_merge and not verbose: continue short_hash = commit.hexsha[:7] first_line = commit.message.splitlines()[0] # TODO make configurable specification = specifications.get_specification( commit.message, allowed_formats, allowed_schemes) if specification.valid: click.secho(' ✔ ', bg='green', fg='white', nl=False) elif is_a_merge: click.secho(' ', fg='yellow', nl=False) else: invalid += 1 click.secho(' ✘ ', bg='red', fg='white', nl=False) click.secho(' {} '.format(short_hash), fg='white' if is_a_merge else 'yellow', nl=False, dim=is_a_merge) click.secho(first_line, dim=is_a_merge) if invalid: if invalid == 1: message = '1 commit has invalid specification.' else: message = '{n} commits have invalid specifications.'.format( n=invalid) click.secho(message, fg='red', bold=True) sys.exit(invalid)
def cmd(reference='HEAD'): """ Opens the specification for commit """ repository = git.get_repository() if not repository: click.secho('This command must be executed inside a repository.', fg='red', bold=True) raise click.Abort options = config.load_repository_configuration(repository.working_dir).get('specification', {}) allowed_schemes = options.get('allowed_schemes', ['https', 'offline']) allowed_formats = options.get('allowed_formats', {'uri'}) try: commit = repository.commit(reference) except git.BadName: click.secho("'{reference}' is not a valid commit reference.".format(reference=reference), fg='red', bold=True) raise click.Abort specification = specifications.get_specification(commit.message, allowed_formats, allowed_schemes) specification_format = specification.format if not specification_format: click.secho("That commit doesn't have a valid specification.", fg='red', bold=True) raise click.Abort if specification_format == 'uri': url = specification.identifier elif specification_format == 'github': origin = repository.remote('origin') # type: git.remote.Remote git_url = origin.config_reader.get('url') repository = github.extract_repository_from_url(git_url) if repository: issue = github.extract_issue_number(specification.identifier) url = 'https://github.com/{repository}/issues/{issue}'.format(**locals()) else: click.secho("{} is not a github repository.".format(git_url), fg='red', bold=True) raise click.Abort else: url = None if url: click.secho('Opening {}'.format(url)) webbrowser.open(url) else: click.secho("{} specifications aren't supported yet.".format(specification_format), fg='red', bold=True) raise click.Abort
def cmd(verbose, revision_range): """ Verifies if the commit messages in a range of revisions have valid specifications. This command takes the same revision ranges as ``git log`` to specify which commits are processed When using the verbose mode merge commits are printed otherwise they are simply ignored """ repository = git.get_repository() if not repository: click.secho('This command must be executed inside a repository.', fg='red', bold=True) raise click.Abort commits = list(repository.iter_commits(revision_range)) invalid = 0 options = config.load_repository_configuration(repository.working_dir).get('specification', {}) allowed_schemes = options.get('allowed_schemes', ['https', 'offline']) allowed_formats = options.get('allowed_formats', {'uri'}) for commit in commits: is_a_merge = len(commit.parents) > 1 if is_a_merge and not verbose: continue short_hash = commit.hexsha[:7] first_line = commit.message.splitlines()[0] # TODO make configurable specification = specifications.get_specification(commit.message, allowed_formats, allowed_schemes) if specification.valid: click.secho(' ✔ ', bg='green', fg='white', nl=False) elif is_a_merge: click.secho(' ', fg='yellow', nl=False) else: invalid += 1 click.secho(' ✘ ', bg='red', fg='white', nl=False) click.secho(' {} '.format(short_hash), fg='white' if is_a_merge else 'yellow', nl=False, dim=is_a_merge) click.secho(first_line, dim=is_a_merge) if invalid: if invalid == 1: message = '1 commit has invalid specification.' else: message = '{n} commits have invalid specifications.'.format(n=invalid) click.secho(message, fg='red', bold=True) sys.exit(invalid)
def check(user_configuration, repository_configuration, commit_message): """ Check if the specification is valid. :param user_configuration: User specific configuration :type user_configuration: git_hooks.common.config.UserConfiguration :param repository_configuration: Repository specific configuration :type repository_configuration: dict :param commit_message: :type commit_message: git_hooks.models.message.CommitMessage :return: If check passed or not :rtype: git_hooks.checks.CheckResult """ logger = output.get_sub_logger('commit-msg', 'specification') logger.debug('Starting specification check...') logger.debug('Commit Message: %s', commit_message.message) if commit_message.message.startswith('Merge'): logger.debug("Commit is a merge, ignoring.") raise checks.CheckIgnore check_options = repository_configuration.get('specification', {}) allowed_schemes = check_options.get('allowed_schemes', ['https', 'offline']) allowed_formats = check_options.get('allowed_formats', {'uri'}) logger.debug("Allowed schemes: %s", allowed_schemes) result = checks.CheckResult() specification = specifications.get_specification(commit_message.message, allowed_formats, allowed_schemes) is_valid_uri = specification.valid logger.debug('Specification: %s', specification) logger.debug("Specification is valid: %s", is_valid_uri) result.successful = is_valid_uri if not is_valid_uri: result.add_detail( '{spec} is not a valid specification.'.format(spec=specification)) return result
def check(user_configuration, repository_configuration, commit_message): """ Check if the specification is valid. :param user_configuration: User specific configuration :type user_configuration: git_hooks.common.config.UserConfiguration :param repository_configuration: Repository specific configuration :type repository_configuration: dict :param commit_message: :type commit_message: git_hooks.models.message.CommitMessage :return: If check passed or not :rtype: git_hooks.checks.CheckResult """ logger = output.get_sub_logger("commit-msg", "specification") logger.debug("Starting specification check...") logger.debug("Commit Message: %s", commit_message.message) if commit_message.message.startswith("Merge"): logger.debug("Commit is a merge, ignoring.") raise checks.CheckIgnore check_options = repository_configuration.get("specification", {}) allowed_schemes = check_options.get("allowed_schemes", ["https", "offline"]) allowed_formats = check_options.get("allowed_formats", {"uri"}) logger.debug("Allowed schemes: %s", allowed_schemes) result = checks.CheckResult() specification = specifications.get_specification(commit_message.message, allowed_formats, allowed_schemes) is_valid_uri = specification.valid logger.debug("Specification: %s", specification) logger.debug("Specification is valid: %s", is_valid_uri) result.successful = is_valid_uri if not is_valid_uri: result.add_detail("{spec} is not a valid specification.".format(spec=specification)) return result
def cmd(reference='HEAD'): """ Opens the specification for commit """ repository = git.get_repository() if not repository: click.secho('This command must be executed inside a repository.', fg='red', bold=True) raise click.Abort options = config.load_repository_configuration(repository.working_dir).get( 'specification', {}) allowed_schemes = options.get('allowed_schemes', ['https', 'offline']) allowed_formats = options.get('allowed_formats', {'uri'}) try: commit = repository.commit(reference) except git.BadName: click.secho("'{reference}' is not a valid commit reference.".format( reference=reference), fg='red', bold=True) raise click.Abort specification = specifications.get_specification(commit.message, allowed_formats, allowed_schemes) specification_format = specification.format if not specification_format: click.secho("That commit doesn't have a valid specification.", fg='red', bold=True) raise click.Abort if specification_format == 'uri': url = specification.identifier elif specification_format == 'github': origin = repository.remote('origin') # type: git.remote.Remote git_url = origin.config_reader.get('url') repository = github.extract_repository_from_url(git_url) if repository: issue = github.extract_issue_number(specification.identifier) url = 'https://github.com/{repository}/issues/{issue}'.format( **locals()) else: click.secho("{} is not a github repository.".format(git_url), fg='red', bold=True) raise click.Abort else: url = None if url: click.secho('Opening {}'.format(url)) webbrowser.open(url) else: click.secho("{} specifications aren't supported yet.".format( specification_format), fg='red', bold=True) raise click.Abort