Show More
@@ -1816,6 +1816,17 b' self: super: {' | |||
|
1816 | 1816 | license = [ pkgs.lib.licenses.mit ]; |
|
1817 | 1817 | }; |
|
1818 | 1818 | }; |
|
1819 | "regex" = super.buildPythonPackage { | |
|
1820 | name = "regex-2020.9.27"; | |
|
1821 | doCheck = false; | |
|
1822 | src = fetchurl { | |
|
1823 | url = "https://files.pythonhosted.org/packages/93/8c/17f45cdfb39b13d4b5f909e4b4c2917abcbdef9c0036919a0399769148cf/regex-2020.9.27.tar.gz"; | |
|
1824 | sha256 = "179ngfzwbsjvn5vhyzdahvmg0f7acahkwwy9bpjy1pv08bm2mwx6"; | |
|
1825 | }; | |
|
1826 | meta = { | |
|
1827 | license = [ pkgs.lib.licenses.psfl ]; | |
|
1828 | }; | |
|
1829 | }; | |
|
1819 | 1830 | "redis" = super.buildPythonPackage { |
|
1820 | 1831 | name = "redis-3.4.1"; |
|
1821 | 1832 | doCheck = false; |
@@ -1946,6 +1957,7 b' self: super: {' | |||
|
1946 | 1957 | self."tzlocal" |
|
1947 | 1958 | self."pyzmq" |
|
1948 | 1959 | self."py-gfm" |
|
1960 | self."regex" | |
|
1949 | 1961 | self."redis" |
|
1950 | 1962 | self."repoze.lru" |
|
1951 | 1963 | self."requests" |
@@ -56,6 +56,7 b' pytz==2019.3' | |||
|
56 | 56 | tzlocal==1.5.1 |
|
57 | 57 | pyzmq==14.6.0 |
|
58 | 58 | py-gfm==0.1.4 |
|
59 | regex==2020.9.27 | |
|
59 | 60 | redis==3.4.1 |
|
60 | 61 | repoze.lru==0.7 |
|
61 | 62 | requests==2.22.0 |
@@ -474,9 +474,18 b' class AdminSettingsView(BaseAppView):' | |||
|
474 | 474 | route_name='admin_settings_issuetracker_test', request_method='POST', |
|
475 | 475 | renderer='string', xhr=True) |
|
476 | 476 | def settings_issuetracker_test(self): |
|
477 | return h.urlify_commit_message( | |
|
477 | error_container = [] | |
|
478 | ||
|
479 | urlified_commit = h.urlify_commit_message( | |
|
478 | 480 | self.request.POST.get('test_text', ''), |
|
479 | 'repo_group/test_repo1') | |
|
481 | 'repo_group/test_repo1', error_container=error_container) | |
|
482 | if error_container: | |
|
483 | def converter(inp): | |
|
484 | return h.html_escape(unicode(inp)) | |
|
485 | ||
|
486 | return 'ERRORS: ' + '\n'.join(map(converter, error_container)) | |
|
487 | ||
|
488 | return urlified_commit | |
|
480 | 489 | |
|
481 | 490 | @LoginRequired() |
|
482 | 491 | @HasPermissionAllDecorator('hg.admin') |
@@ -113,7 +113,7 b' def _commits_as_dict(event, commit_ids, ' | |||
|
113 | 113 | cs_data['permalink_url'] = RepoModel().get_commit_url( |
|
114 | 114 | repo, cs_data['raw_id'], request=event.request, |
|
115 | 115 | permalink=True) |
|
116 | urlified_message, issues_data = process_patterns( | |
|
116 | urlified_message, issues_data, errors = process_patterns( | |
|
117 | 117 | cs_data['message'], repo.repo_name) |
|
118 | 118 | cs_data['issues'] = issues_data |
|
119 | 119 | cs_data['message_html'] = urlify_commit_message( |
@@ -38,6 +38,7 b' import re' | |||
|
38 | 38 | import time |
|
39 | 39 | import string |
|
40 | 40 | import hashlib |
|
41 | import regex | |
|
41 | 42 | from collections import OrderedDict |
|
42 | 43 | |
|
43 | 44 | import pygments |
@@ -1653,7 +1654,7 b' def get_active_pattern_entries(repo_name' | |||
|
1653 | 1654 | return active_entries |
|
1654 | 1655 | |
|
1655 | 1656 | |
|
1656 | pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)') | |
|
1657 | pr_pattern_re = regex.compile(r'(?:(?:^!)|(?: !))(\d+)') | |
|
1657 | 1658 | |
|
1658 | 1659 | allowed_link_formats = [ |
|
1659 | 1660 | 'html', 'rst', 'markdown', 'html+hovercard', 'rst+hovercard', 'markdown+hovercard'] |
@@ -1670,6 +1671,7 b' def process_patterns(text_string, repo_n' | |||
|
1670 | 1671 | active_entries = get_active_pattern_entries(repo_name) |
|
1671 | 1672 | |
|
1672 | 1673 | issues_data = [] |
|
1674 | errors = [] | |
|
1673 | 1675 | new_text = text_string |
|
1674 | 1676 | |
|
1675 | 1677 | log.debug('Got %s entries to process', len(active_entries)) |
@@ -1687,9 +1689,11 b' def process_patterns(text_string, repo_n' | |||
|
1687 | 1689 | pattern = entry['pat_compiled'] |
|
1688 | 1690 | else: |
|
1689 | 1691 | try: |
|
1690 | pattern = re.compile(r'%s' % entry['pat']) | |
|
1691 | except re.error: | |
|
1692 | log.exception('issue tracker pattern: `%s` failed to compile', entry['pat']) | |
|
1692 | pattern = regex.compile(r'%s' % entry['pat']) | |
|
1693 | except regex.error as e: | |
|
1694 | regex_err = ValueError('{}:{}'.format(entry['pat'], e)) | |
|
1695 | log.exception('issue tracker pattern: `%s` failed to compile', regex_err) | |
|
1696 | errors.append(regex_err) | |
|
1693 | 1697 | continue |
|
1694 | 1698 | |
|
1695 | 1699 | data_func = partial( |
@@ -1721,11 +1725,11 b' def process_patterns(text_string, repo_n' | |||
|
1721 | 1725 | new_text = pr_pattern_re.sub(pr_url_func, new_text) |
|
1722 | 1726 | log.debug('processed !pr pattern') |
|
1723 | 1727 | |
|
1724 | return new_text, issues_data | |
|
1728 | return new_text, issues_data, errors | |
|
1725 | 1729 | |
|
1726 | 1730 | |
|
1727 | 1731 | def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None, |
|
1728 | issues_container=None): | |
|
1732 | issues_container=None, error_container=None): | |
|
1729 | 1733 | """ |
|
1730 | 1734 | Parses given text message and makes proper links. |
|
1731 | 1735 | issues are linked to given issue-server, and rest is a commit link |
@@ -1745,12 +1749,15 b' def urlify_commit_message(commit_text, r' | |||
|
1745 | 1749 | new_text = urlify_commits(new_text, repository) |
|
1746 | 1750 | |
|
1747 | 1751 | # process issue tracker patterns |
|
1748 |
new_text, issues = process_patterns( |
|
|
1749 |
|
|
|
1752 | new_text, issues, errors = process_patterns( | |
|
1753 | new_text, repository or '', active_entries=active_pattern_entries) | |
|
1750 | 1754 | |
|
1751 | 1755 | if issues_container is not None: |
|
1752 | 1756 | issues_container.extend(issues) |
|
1753 | 1757 | |
|
1758 | if error_container is not None: | |
|
1759 | error_container.extend(errors) | |
|
1760 | ||
|
1754 | 1761 | return literal(new_text) |
|
1755 | 1762 | |
|
1756 | 1763 | |
@@ -1805,7 +1812,7 b" def render(source, renderer='rst', menti" | |||
|
1805 | 1812 | elif renderer == 'rst': |
|
1806 | 1813 | if repo_name: |
|
1807 | 1814 | # process patterns on comments if we pass in repo name |
|
1808 | source, issues = process_patterns( | |
|
1815 | source, issues, errors = process_patterns( | |
|
1809 | 1816 | source, repo_name, link_format='rst', |
|
1810 | 1817 | active_entries=active_pattern_entries) |
|
1811 | 1818 | if issues_container is not None: |
@@ -1819,7 +1826,7 b" def render(source, renderer='rst', menti" | |||
|
1819 | 1826 | elif renderer == 'markdown': |
|
1820 | 1827 | if repo_name: |
|
1821 | 1828 | # process patterns on comments if we pass in repo name |
|
1822 | source, issues = process_patterns( | |
|
1829 | source, issues, errors = process_patterns( | |
|
1823 | 1830 | source, repo_name, link_format='markdown', |
|
1824 | 1831 | active_entries=active_pattern_entries) |
|
1825 | 1832 | if issues_container is not None: |
@@ -16,8 +16,8 b' examples = [' | |||
|
16 | 16 | ), |
|
17 | 17 | |
|
18 | 18 | ( |
|
19 | 'Redmine', | |
|
20 |
'( |
|
|
19 | 'Tickets with #123 (Redmine etc)', | |
|
20 | '(?<![a-zA-Z0-9_/]{1,10}-?)(#)(?P<issue_id>\d+)', | |
|
21 | 21 | 'https://myissueserver.com/${repo}/issue/${issue_id}', |
|
22 | 22 | '' |
|
23 | 23 | ), |
@@ -38,14 +38,15 b' examples = [' | |||
|
38 | 38 | |
|
39 | 39 | ( |
|
40 | 40 | 'JIRA - All tickets', |
|
41 | '(^|\s\w+-\d+)', | |
|
42 | 'https://myjira.com/browse/${id}', | |
|
41 | # official JIRA ticket pattern | |
|
42 | '(?<![a-zA-Z0-9_/#]-?)(?P<issue_id>[A-Z]{1,6}-(?:[1-9][0-9]{0,7}))', | |
|
43 | 'https://myjira.com/browse/${issue_id}', | |
|
43 | 44 | '' |
|
44 | 45 | ), |
|
45 | 46 | |
|
46 | 47 | ( |
|
47 |
'JIRA - |
|
|
48 | '(?:(^|\s)(?P<issue_id>(?:JRA-|JRA-)(?:\d+)))', | |
|
48 | 'JIRA - Single project (JRA-XXXXXXXX)', | |
|
49 | '(?<![a-zA-Z0-9_/#]-?)(?P<issue_id>JRA-(?:[1-9][0-9]{0,7}))', | |
|
49 | 50 | 'https://myjira.com/${issue_id}', |
|
50 | 51 | '' |
|
51 | 52 | ), |
@@ -275,12 +276,18 b' examples = [' | |||
|
275 | 276 | <div class='textarea-full'> |
|
276 | 277 | <textarea id="test_pattern_data" rows="12"> |
|
277 | 278 | This is an example text for testing issue tracker patterns. |
|
278 | This commit fixes ticket #451 and ticket #910. | |
|
279 |
|
|
|
279 | This commit fixes ticket #451 and ticket #910, reference for JRA-401. | |
|
280 | The following tickets will get mentioned: | |
|
280 | 281 | #123 |
|
281 | #456 | |
|
282 | JRA-123 | |
|
283 |
J |
|
|
282 | #456 and PROJ-101 | |
|
283 | JRA-123 and #123 | |
|
284 | PROJ-456 | |
|
285 | ||
|
286 | [my artifact](http://something.com/JRA-1234-build.zip) | |
|
287 | ||
|
288 | - #1001 | |
|
289 | - JRA-998 | |
|
290 | ||
|
284 | 291 |
Open a pull request !101 to contribute |
|
285 | 292 | Added tag v1.3.0 for commit 0f3b629be725 |
|
286 | 293 |
@@ -121,7 +121,7 b' def test_extract_issues(backend, text_st' | |||
|
121 | 121 | |
|
122 | 122 | with mock.patch.object(IssueTrackerSettingsModel, |
|
123 | 123 | 'get_settings', get_settings_mock): |
|
124 | text, issues = helpers.process_patterns(text_string, repo.repo_name) | |
|
124 | text, issues, errors = helpers.process_patterns(text_string, repo.repo_name) | |
|
125 | 125 | |
|
126 | 126 | expected = copy.deepcopy(expected) |
|
127 | 127 | for item in expected: |
@@ -159,7 +159,7 b' def test_process_patterns_repo(backend, ' | |||
|
159 | 159 | |
|
160 | 160 | with mock.patch.object(IssueTrackerSettingsModel, |
|
161 | 161 | 'get_settings', get_settings_mock): |
|
162 | processed_text, issues = helpers.process_patterns( | |
|
162 | processed_text, issues, error = helpers.process_patterns( | |
|
163 | 163 | text_string, repo.repo_name, link_format) |
|
164 | 164 | |
|
165 | 165 | assert processed_text == expected_text.format(repo=repo.repo_name) |
@@ -186,7 +186,7 b' def test_process_patterns_no_repo(text_s' | |||
|
186 | 186 | |
|
187 | 187 | with mock.patch.object(IssueTrackerSettingsModel, |
|
188 | 188 | 'get_global_settings', get_settings_mock): |
|
189 | processed_text, issues = helpers.process_patterns( | |
|
189 | processed_text, issues, errors = helpers.process_patterns( | |
|
190 | 190 | text_string, '') |
|
191 | 191 | |
|
192 | 192 | assert processed_text == expected_text |
@@ -211,7 +211,7 b' def test_process_patterns_non_existent_r' | |||
|
211 | 211 | |
|
212 | 212 | with mock.patch.object(IssueTrackerSettingsModel, |
|
213 | 213 | 'get_global_settings', get_settings_mock): |
|
214 | processed_text, issues = helpers.process_patterns( | |
|
214 | processed_text, issues, errors = helpers.process_patterns( | |
|
215 | 215 | text_string, 'do-not-exist') |
|
216 | 216 | |
|
217 | 217 | assert processed_text == expected_text |
General Comments 0
You need to be logged in to leave comments.
Login now