# HG changeset patch # User Marcin Kuzminski # Date 2020-09-30 08:53:17 # Node ID 2fce90e49da0840e00a6a5db1489b01ab3faa57f # Parent 8b17d3ec011bf35db5bda07c2d302e7b913a7816 issue-trackers: implemented more sophisticated ticket data extraction based on advanced regex module, and special look-behind regex. This is a recommended ticket extraction from Atlassian itself (for Jira) and we also implemented it for Redmine, or tickets - bonus: report errors on patterns in preview window diff --git a/pkgs/python-packages.nix b/pkgs/python-packages.nix --- a/pkgs/python-packages.nix +++ b/pkgs/python-packages.nix @@ -1816,6 +1816,17 @@ self: super: { license = [ pkgs.lib.licenses.mit ]; }; }; + "regex" = super.buildPythonPackage { + name = "regex-2020.9.27"; + doCheck = false; + src = fetchurl { + url = "https://files.pythonhosted.org/packages/93/8c/17f45cdfb39b13d4b5f909e4b4c2917abcbdef9c0036919a0399769148cf/regex-2020.9.27.tar.gz"; + sha256 = "179ngfzwbsjvn5vhyzdahvmg0f7acahkwwy9bpjy1pv08bm2mwx6"; + }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; + }; "redis" = super.buildPythonPackage { name = "redis-3.4.1"; doCheck = false; @@ -1946,6 +1957,7 @@ self: super: { self."tzlocal" self."pyzmq" self."py-gfm" + self."regex" self."redis" self."repoze.lru" self."requests" diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -56,6 +56,7 @@ pytz==2019.3 tzlocal==1.5.1 pyzmq==14.6.0 py-gfm==0.1.4 +regex==2020.9.27 redis==3.4.1 repoze.lru==0.7 requests==2.22.0 diff --git a/rhodecode/apps/admin/views/settings.py b/rhodecode/apps/admin/views/settings.py --- a/rhodecode/apps/admin/views/settings.py +++ b/rhodecode/apps/admin/views/settings.py @@ -474,9 +474,18 @@ class AdminSettingsView(BaseAppView): route_name='admin_settings_issuetracker_test', request_method='POST', renderer='string', xhr=True) def settings_issuetracker_test(self): - return h.urlify_commit_message( + error_container = [] + + urlified_commit = h.urlify_commit_message( self.request.POST.get('test_text', ''), - 'repo_group/test_repo1') + 'repo_group/test_repo1', error_container=error_container) + if error_container: + def converter(inp): + return h.html_escape(unicode(inp)) + + return 'ERRORS: ' + '\n'.join(map(converter, error_container)) + + return urlified_commit @LoginRequired() @HasPermissionAllDecorator('hg.admin') diff --git a/rhodecode/events/repo.py b/rhodecode/events/repo.py --- a/rhodecode/events/repo.py +++ b/rhodecode/events/repo.py @@ -113,7 +113,7 @@ def _commits_as_dict(event, commit_ids, cs_data['permalink_url'] = RepoModel().get_commit_url( repo, cs_data['raw_id'], request=event.request, permalink=True) - urlified_message, issues_data = process_patterns( + urlified_message, issues_data, errors = process_patterns( cs_data['message'], repo.repo_name) cs_data['issues'] = issues_data cs_data['message_html'] = urlify_commit_message( diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -38,6 +38,7 @@ import re import time import string import hashlib +import regex from collections import OrderedDict import pygments @@ -1653,7 +1654,7 @@ def get_active_pattern_entries(repo_name return active_entries -pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)') +pr_pattern_re = regex.compile(r'(?:(?:^!)|(?: !))(\d+)') allowed_link_formats = [ 'html', 'rst', 'markdown', 'html+hovercard', 'rst+hovercard', 'markdown+hovercard'] @@ -1670,6 +1671,7 @@ def process_patterns(text_string, repo_n active_entries = get_active_pattern_entries(repo_name) issues_data = [] + errors = [] new_text = text_string log.debug('Got %s entries to process', len(active_entries)) @@ -1687,9 +1689,11 @@ def process_patterns(text_string, repo_n pattern = entry['pat_compiled'] else: try: - pattern = re.compile(r'%s' % entry['pat']) - except re.error: - log.exception('issue tracker pattern: `%s` failed to compile', entry['pat']) + pattern = regex.compile(r'%s' % entry['pat']) + except regex.error as e: + regex_err = ValueError('{}:{}'.format(entry['pat'], e)) + log.exception('issue tracker pattern: `%s` failed to compile', regex_err) + errors.append(regex_err) continue data_func = partial( @@ -1721,11 +1725,11 @@ def process_patterns(text_string, repo_n new_text = pr_pattern_re.sub(pr_url_func, new_text) log.debug('processed !pr pattern') - return new_text, issues_data + return new_text, issues_data, errors def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None, - issues_container=None): + issues_container=None, error_container=None): """ Parses given text message and makes proper links. issues are linked to given issue-server, and rest is a commit link @@ -1745,12 +1749,15 @@ def urlify_commit_message(commit_text, r new_text = urlify_commits(new_text, repository) # process issue tracker patterns - new_text, issues = process_patterns(new_text, repository or '', - active_entries=active_pattern_entries) + new_text, issues, errors = process_patterns( + new_text, repository or '', active_entries=active_pattern_entries) if issues_container is not None: issues_container.extend(issues) + if error_container is not None: + error_container.extend(errors) + return literal(new_text) @@ -1805,7 +1812,7 @@ def render(source, renderer='rst', menti elif renderer == 'rst': if repo_name: # process patterns on comments if we pass in repo name - source, issues = process_patterns( + source, issues, errors = process_patterns( source, repo_name, link_format='rst', active_entries=active_pattern_entries) if issues_container is not None: @@ -1819,7 +1826,7 @@ def render(source, renderer='rst', menti elif renderer == 'markdown': if repo_name: # process patterns on comments if we pass in repo name - source, issues = process_patterns( + source, issues, errors = process_patterns( source, repo_name, link_format='markdown', active_entries=active_pattern_entries) if issues_container is not None: diff --git a/rhodecode/templates/base/issue_tracker_settings.mako b/rhodecode/templates/base/issue_tracker_settings.mako --- a/rhodecode/templates/base/issue_tracker_settings.mako +++ b/rhodecode/templates/base/issue_tracker_settings.mako @@ -16,8 +16,8 @@ examples = [ ), ( - 'Redmine', - '(^#|\s#)(?P\d+)', + 'Tickets with #123 (Redmine etc)', + '(?\d+)', 'https://myissueserver.com/${repo}/issue/${issue_id}', '' ), @@ -38,14 +38,15 @@ examples = [ ( 'JIRA - All tickets', - '(^|\s\w+-\d+)', - 'https://myjira.com/browse/${id}', + # official JIRA ticket pattern + '(?[A-Z]{1,6}-(?:[1-9][0-9]{0,7}))', + 'https://myjira.com/browse/${issue_id}', '' ), ( - 'JIRA - Project (JRA)', - '(?:(^|\s)(?P(?:JRA-|JRA-)(?:\d+)))', + 'JIRA - Single project (JRA-XXXXXXXX)', + '(?JRA-(?:[1-9][0-9]{0,7}))', 'https://myjira.com/${issue_id}', '' ), @@ -275,13 +276,19 @@ examples = [