Accepting request 837239 from devel:tools:scm
- Backport various fixes from upstream + Patch: 0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch + Patch: 0002-Show-the-assignee-s-avatar-on-the-board.patch + Patch: 0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch + Patch: 0004-Include-the-assignee-in-the-list-of-people-notified-.patch + Patch: 0005-Introduce-the-collaborator_project_groups-mapping.patch + Patch: 0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch + Patch: 0007-Remove-fenced-code-block-when-checking-mention.patch + Patch: 0008-Add-support-for-using-cchardet-to-detect-files-encod.patch + Patch: 0009-Add-support-for-disabling-user-registration.patch - Remove mandatory dependency on systemd to ease containerization OBS-URL: https://build.opensuse.org/request/show/837239 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/pagure?expand=0&rev=19
This commit is contained in:
commit
028f8f9ec9
194
0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
Normal file
194
0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
From f48278682d9552670b7d5cb9e99a7e0a74bdd689 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julen Landa Alustiza <jlanda@fedoraproject.org>
|
||||||
|
Date: Fri, 7 Aug 2020 12:35:32 +0200
|
||||||
|
Subject: [PATCH 1/9] Display real line numbers on pull request's diff view
|
||||||
|
Fixes #724
|
||||||
|
|
||||||
|
---
|
||||||
|
pagure/templates/_repo_renderdiff.html | 1 -
|
||||||
|
pagure/ui/filters.py | 101 ++++++++++---------------
|
||||||
|
tests/test_pagure_flask_ui_fork.py | 24 +++++-
|
||||||
|
3 files changed, 64 insertions(+), 62 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pagure/templates/_repo_renderdiff.html b/pagure/templates/_repo_renderdiff.html
|
||||||
|
index a0922169..aa9a062e 100644
|
||||||
|
--- a/pagure/templates/_repo_renderdiff.html
|
||||||
|
+++ b/pagure/templates/_repo_renderdiff.html
|
||||||
|
@@ -164,7 +164,6 @@
|
||||||
|
commit=patchstats["new_id"],
|
||||||
|
prequest=pull_request,
|
||||||
|
index=loop.index,
|
||||||
|
- isprdiff=True,
|
||||||
|
tree_id=diff_commits[0].tree.id)}}
|
||||||
|
</div>
|
||||||
|
{% endautoescape %}
|
||||||
|
diff --git a/pagure/ui/filters.py b/pagure/ui/filters.py
|
||||||
|
index 73799ed7..98b2741f 100644
|
||||||
|
--- a/pagure/ui/filters.py
|
||||||
|
+++ b/pagure/ui/filters.py
|
||||||
|
@@ -149,38 +149,33 @@ def format_loc(
|
||||||
|
for key in comments:
|
||||||
|
comments[key] = sorted(comments[key], key=lambda obj: obj.date_created)
|
||||||
|
|
||||||
|
- if not index:
|
||||||
|
- index = ""
|
||||||
|
+ if isinstance(filename, str) and six.PY2:
|
||||||
|
+ filename = filename.decode("UTF-8")
|
||||||
|
|
||||||
|
cnt = 1
|
||||||
|
for line in loc.split("\n"):
|
||||||
|
- if filename and commit:
|
||||||
|
- if isinstance(filename, str) and six.PY2:
|
||||||
|
- filename = filename.decode("UTF-8")
|
||||||
|
-
|
||||||
|
- if isprdiff and (
|
||||||
|
- line.startswith("@@")
|
||||||
|
- or line.startswith("+")
|
||||||
|
- or line.startswith("-")
|
||||||
|
- ):
|
||||||
|
- if line.startswith("@@"):
|
||||||
|
- output.append(
|
||||||
|
- '<tr class="stretch-table-column bg-light"\
|
||||||
|
- id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
- % ({"cnt_lbl": cnt, "commit": commit})
|
||||||
|
- )
|
||||||
|
- elif line.startswith("+"):
|
||||||
|
- output.append(
|
||||||
|
- '<tr class="stretch-table-column alert-success" \
|
||||||
|
- id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
- % ({"cnt_lbl": cnt, "commit": commit})
|
||||||
|
- )
|
||||||
|
- elif line.startswith("-"):
|
||||||
|
- output.append(
|
||||||
|
- '<tr class="stretch-table-column alert-danger" \
|
||||||
|
- id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
- % ({"cnt_lbl": cnt, "commit": commit})
|
||||||
|
- )
|
||||||
|
+ if line.startswith("@@"):
|
||||||
|
+ output.append(
|
||||||
|
+ '<tr class="stretch-table-column bg-light"\
|
||||||
|
+ id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
+ % ({"cnt_lbl": cnt, "commit": commit})
|
||||||
|
+ )
|
||||||
|
+ output.append(
|
||||||
|
+ '<td class="cell1"></td><td class="prc border-right"></td>'
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ if line.startswith("+"):
|
||||||
|
+ output.append(
|
||||||
|
+ '<tr class="stretch-table-column alert-success" \
|
||||||
|
+ id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
+ % ({"cnt_lbl": cnt, "commit": commit})
|
||||||
|
+ )
|
||||||
|
+ elif line.startswith("-"):
|
||||||
|
+ output.append(
|
||||||
|
+ '<tr class="stretch-table-column alert-danger" \
|
||||||
|
+ id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
+ % ({"cnt_lbl": cnt, "commit": commit})
|
||||||
|
+ )
|
||||||
|
else:
|
||||||
|
output.append(
|
||||||
|
'<tr id="c-%(commit)s-%(cnt_lbl)s">'
|
||||||
|
@@ -211,13 +206,6 @@ def format_loc(
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
- else:
|
||||||
|
- output.append(
|
||||||
|
- '<tr><td class="cell1">'
|
||||||
|
- '<a id="%(cnt)s" href="#%(cnt)s" data-line-number='
|
||||||
|
- '"%(cnt_lbl)s"></a></td>'
|
||||||
|
- % ({"cnt": "%s_%s" % (index, cnt), "cnt_lbl": cnt})
|
||||||
|
- )
|
||||||
|
|
||||||
|
cnt += 1
|
||||||
|
if not line:
|
||||||
|
@@ -254,29 +242,24 @@ def format_loc(
|
||||||
|
+ 'title="Open changed file"></span></a>'
|
||||||
|
)
|
||||||
|
|
||||||
|
- if isprdiff and (
|
||||||
|
- line.startswith("@@")
|
||||||
|
- or line.startswith("+")
|
||||||
|
- or line.startswith("-")
|
||||||
|
- ):
|
||||||
|
- if line.startswith("@@"):
|
||||||
|
- output.append(
|
||||||
|
- '<td class="cell2 stretch-table-column">\
|
||||||
|
- <pre class="text-muted"><code>%s</code></pre></td>'
|
||||||
|
- % line
|
||||||
|
- )
|
||||||
|
- elif line.startswith("+"):
|
||||||
|
- output.append(
|
||||||
|
- '<td class="cell2 stretch-table-column">\
|
||||||
|
- <pre class="alert-success"><code>%s</code></pre></td>'
|
||||||
|
- % escape(line)
|
||||||
|
- )
|
||||||
|
- elif line.startswith("-"):
|
||||||
|
- output.append(
|
||||||
|
- '<td class="cell2 stretch-table-column">\
|
||||||
|
- <pre class="alert-danger"><code>%s</code></pre></td>'
|
||||||
|
- % escape(line)
|
||||||
|
- )
|
||||||
|
+ if line.startswith("@@"):
|
||||||
|
+ output.append(
|
||||||
|
+ '<td class="cell2 stretch-table-column">\
|
||||||
|
+ <pre class="text-muted"><code>%s</code></pre></td>'
|
||||||
|
+ % line
|
||||||
|
+ )
|
||||||
|
+ elif line.startswith("+"):
|
||||||
|
+ output.append(
|
||||||
|
+ '<td class="cell2 stretch-table-column">\
|
||||||
|
+ <pre class="alert-success"><code>%s</code></pre></td>'
|
||||||
|
+ % escape(line)
|
||||||
|
+ )
|
||||||
|
+ elif line.startswith("-"):
|
||||||
|
+ output.append(
|
||||||
|
+ '<td class="cell2 stretch-table-column">\
|
||||||
|
+ <pre class="alert-danger"><code>%s</code></pre></td>'
|
||||||
|
+ % escape(line)
|
||||||
|
+ )
|
||||||
|
else:
|
||||||
|
output.append(
|
||||||
|
'<td class="cell2"><pre><code>%s</code></pre></td>'
|
||||||
|
diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py
|
||||||
|
index 21ecd7df..8e8dce1c 100644
|
||||||
|
--- a/tests/test_pagure_flask_ui_fork.py
|
||||||
|
+++ b/tests/test_pagure_flask_ui_fork.py
|
||||||
|
@@ -302,11 +302,31 @@ class PagureFlaskForktests(tests.Modeltests):
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIn(
|
||||||
|
- '<span class="btn btn-success btn-sm font-weight-bold disabled opacity-100">+3</span>',
|
||||||
|
+ '<span class="btn btn-success btn-sm font-weight-bold disabled'
|
||||||
|
+ ' opacity-100">+3</span>',
|
||||||
|
output_text,
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
- '<span class="btn btn-danger btn-sm font-weight-bold disabled opacity-100">-1</span>',
|
||||||
|
+ '<span class="btn btn-danger btn-sm font-weight-bold disabled '
|
||||||
|
+ 'opacity-100">-1</span>',
|
||||||
|
+ output_text,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ # Test if hunk headline is rendered without line numbers
|
||||||
|
+ self.assertIn(
|
||||||
|
+ '<td class="cell1"></td><td class="prc border-right"></td>\n<td '
|
||||||
|
+ 'class="cell2 stretch-table-column"> <pre class='
|
||||||
|
+ '"text-muted"><code>@@ -1,2 +1,4 @@',
|
||||||
|
+ output_text,
|
||||||
|
+ )
|
||||||
|
+ # Tests if line number 1 is displayed
|
||||||
|
+ self.assertNotIn(
|
||||||
|
+ '<td class="cell1"><a id="_1__1" href="#_1__1" data-line-number="1" data-file-number="1"></a></td>',
|
||||||
|
+ output_text,
|
||||||
|
+ )
|
||||||
|
+ # Test if line number 2 is displayed
|
||||||
|
+ self.assertIn(
|
||||||
|
+ '<td class="cell1"><a id="_1__2" href="#_1__2" data-line-number="2" data-file-number="1"></a></td>',
|
||||||
|
output_text,
|
||||||
|
)
|
||||||
|
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
33
0002-Show-the-assignee-s-avatar-on-the-board.patch
Normal file
33
0002-Show-the-assignee-s-avatar-on-the-board.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
From d3fb1c32746580bb109ac21ff349a655a01c46f0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
Date: Wed, 12 Aug 2020 20:47:22 +0200
|
||||||
|
Subject: [PATCH 2/9] Show the assignee's avatar on the board
|
||||||
|
|
||||||
|
If the ticket shown in the board is assigned to someone, show this
|
||||||
|
person's avatar. This helps not only seeing what is in progress or
|
||||||
|
blocked but also who is working on what or being blocked.
|
||||||
|
|
||||||
|
Fixes https://pagure.io/pagure/issue/4959
|
||||||
|
|
||||||
|
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
---
|
||||||
|
pagure/templates/board.html | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pagure/templates/board.html b/pagure/templates/board.html
|
||||||
|
index 26509ae0..46a7eb65 100644
|
||||||
|
--- a/pagure/templates/board.html
|
||||||
|
+++ b/pagure/templates/board.html
|
||||||
|
@@ -65,6 +65,9 @@
|
||||||
|
{% elif bissue.issue.status == 'Closed' %}
|
||||||
|
<span class="fa fa-fw text-danger fa-exclamation-circle pt-1 icon_id"></span>
|
||||||
|
<span class="text-danger font-weight-bold id_txt">#{{ bissue.issue.id }}</span>
|
||||||
|
+ {% endif %}
|
||||||
|
+ {% if bissue.issue.assignee %}
|
||||||
|
+ - {{ bissue.issue.assignee.username | avatar(size=20) | safe}}
|
||||||
|
{% endif %}
|
||||||
|
- {{ bissue.issue.title | truncate(80, False, '...') }}
|
||||||
|
</a>
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
128
0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
Normal file
128
0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
From 9fd32d4d948fc4231eee68e8044b844060db140c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
Date: Wed, 12 Aug 2020 20:56:18 +0200
|
||||||
|
Subject: [PATCH 3/9] Allow setting a status as closing even if the project has
|
||||||
|
no close_status
|
||||||
|
|
||||||
|
When determining if a status "closes" tickets or not, we should first
|
||||||
|
check if it was set to and only if it wasn't then check if there was a
|
||||||
|
close_status set for it. Otherwise the logic wasn't correctly interpreted.
|
||||||
|
|
||||||
|
Fixes https://pagure.io/pagure/issue/4958
|
||||||
|
|
||||||
|
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
---
|
||||||
|
pagure/api/boards.py | 4 +-
|
||||||
|
tests/test_pagure_flask_api_boards.py | 81 +++++++++++++++++++++++++++
|
||||||
|
2 files changed, 84 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/pagure/api/boards.py b/pagure/api/boards.py
|
||||||
|
index e42f7cb6..669fd457 100644
|
||||||
|
--- a/pagure/api/boards.py
|
||||||
|
+++ b/pagure/api/boards.py
|
||||||
|
@@ -510,7 +510,9 @@ def api_board_status(repo, board_name, username=None, namespace=None):
|
||||||
|
|
||||||
|
try:
|
||||||
|
close_status = data[name].get("close_status") or None
|
||||||
|
- close = data[name].get("close") or True if close_status else False
|
||||||
|
+ close = data[name].get("close") or (
|
||||||
|
+ True if close_status else False
|
||||||
|
+ )
|
||||||
|
if close_status not in repo.close_status:
|
||||||
|
close_status = None
|
||||||
|
|
||||||
|
diff --git a/tests/test_pagure_flask_api_boards.py b/tests/test_pagure_flask_api_boards.py
|
||||||
|
index ef125878..67199703 100644
|
||||||
|
--- a/tests/test_pagure_flask_api_boards.py
|
||||||
|
+++ b/tests/test_pagure_flask_api_boards.py
|
||||||
|
@@ -801,6 +801,87 @@ class PagureFlaskApiBoardsWithBoardtests(tests.SimplePagureTest):
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
+ def test_api_board_api_board_status_no_close_status(self):
|
||||||
|
+ headers = {
|
||||||
|
+ "Authorization": "token aaabbbcccddd",
|
||||||
|
+ "Content-Type": "application/json",
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ data = json.dumps(
|
||||||
|
+ {
|
||||||
|
+ "Backlog": {
|
||||||
|
+ "close": False,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "bg_color": "#FFB300",
|
||||||
|
+ "default": True,
|
||||||
|
+ "rank": 1,
|
||||||
|
+ },
|
||||||
|
+ "Triaged": {
|
||||||
|
+ "close": False,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "bg_color": "#ca0dcd",
|
||||||
|
+ "default": False,
|
||||||
|
+ "rank": 2,
|
||||||
|
+ },
|
||||||
|
+ "Done": {
|
||||||
|
+ "close": True,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "bg_color": "#34d240",
|
||||||
|
+ "default": False,
|
||||||
|
+ "rank": 4,
|
||||||
|
+ },
|
||||||
|
+ " ": {
|
||||||
|
+ "close": True,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "bg_color": "#34d240",
|
||||||
|
+ "default": False,
|
||||||
|
+ "rank": 5,
|
||||||
|
+ },
|
||||||
|
+ }
|
||||||
|
+ )
|
||||||
|
+ output = self.app.post(
|
||||||
|
+ "/api/0/test/boards/dev/status", headers=headers, data=data
|
||||||
|
+ )
|
||||||
|
+ self.assertEqual(output.status_code, 200)
|
||||||
|
+ data = json.loads(output.get_data(as_text=True))
|
||||||
|
+ self.assertDictEqual(
|
||||||
|
+ data,
|
||||||
|
+ {
|
||||||
|
+ "board": {
|
||||||
|
+ "active": True,
|
||||||
|
+ "name": "dev",
|
||||||
|
+ "status": [
|
||||||
|
+ {
|
||||||
|
+ "bg_color": "#FFB300",
|
||||||
|
+ "close": False,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "default": True,
|
||||||
|
+ "name": "Backlog",
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ "bg_color": "#ca0dcd",
|
||||||
|
+ "close": False,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "default": False,
|
||||||
|
+ "name": "Triaged",
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ "name": "Done",
|
||||||
|
+ "close": True,
|
||||||
|
+ "close_status": None,
|
||||||
|
+ "default": False,
|
||||||
|
+ "bg_color": "#34d240",
|
||||||
|
+ },
|
||||||
|
+ ],
|
||||||
|
+ "tag": {
|
||||||
|
+ "tag": "dev",
|
||||||
|
+ "tag_color": "DeepBlueSky",
|
||||||
|
+ "tag_description": "",
|
||||||
|
+ },
|
||||||
|
+ }
|
||||||
|
+ },
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
def test_api_board_api_board_status_adding_removing(self):
|
||||||
|
headers = {
|
||||||
|
"Authorization": "token aaabbbcccddd",
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
From 1e129038cf63f619fd5b69f92057cb29c53a83d3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
Date: Wed, 12 Aug 2020 21:19:22 +0200
|
||||||
|
Subject: [PATCH 4/9] Include the assignee in the list of people notified on a
|
||||||
|
ticket/PR
|
||||||
|
|
||||||
|
We always include the assignee in the notifications (even on private
|
||||||
|
tickets), but so far we did not show them in the list of subscriber.
|
||||||
|
|
||||||
|
With this commit, this oversight is now fixed.
|
||||||
|
|
||||||
|
Fixes https://pagure.io/pagure/issue/4957
|
||||||
|
|
||||||
|
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
---
|
||||||
|
pagure/lib/query.py | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pagure/lib/query.py b/pagure/lib/query.py
|
||||||
|
index 8ee4df6c..498148df 100644
|
||||||
|
--- a/pagure/lib/query.py
|
||||||
|
+++ b/pagure/lib/query.py
|
||||||
|
@@ -4957,6 +4957,10 @@ def get_watch_list(session, obj):
|
||||||
|
# Add the user of the project
|
||||||
|
users.add(obj.project.user.username)
|
||||||
|
|
||||||
|
+ # Add the assignee if there is one
|
||||||
|
+ if obj.assignee:
|
||||||
|
+ users.add(obj.assignee.username)
|
||||||
|
+
|
||||||
|
# Add the regular contributors
|
||||||
|
for contributor in obj.project.users:
|
||||||
|
users.add(contributor.username)
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
104
0005-Introduce-the-collaborator_project_groups-mapping.patch
Normal file
104
0005-Introduce-the-collaborator_project_groups-mapping.patch
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
From d91182e9bd01582c3ba1671a758038819943fb9b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
Date: Tue, 18 Aug 2020 13:33:21 +0200
|
||||||
|
Subject: [PATCH 5/9] Introduce the collaborator_project_groups mapping
|
||||||
|
|
||||||
|
We need two mappings on a regular basis. One linking a project to its
|
||||||
|
group of collaborator and pointing to the PagureGroup objects directly.
|
||||||
|
This is used for example to retrieve the list of collaborator groups.
|
||||||
|
The one mapping is between a project and the corresponding ProjectGroup
|
||||||
|
for collaborators which is where the "branches" that the group is
|
||||||
|
restricted to is stored.
|
||||||
|
|
||||||
|
So we now have both mappings available and we need to be careful to use
|
||||||
|
the proper one, but pagure will quickly indicate (ie: crash) if one
|
||||||
|
uses the wrong one and tries to access either the group name or the
|
||||||
|
branches attribute.
|
||||||
|
|
||||||
|
Fixes https://pagure.io/fedora-infrastructure/issue/9247
|
||||||
|
|
||||||
|
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
---
|
||||||
|
pagure/lib/model.py | 10 ++++++++++
|
||||||
|
pagure/utils.py | 2 +-
|
||||||
|
tests/test_pagure_flask_api_project.py | 23 ++++++++++++++++++++++-
|
||||||
|
3 files changed, 33 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pagure/lib/model.py b/pagure/lib/model.py
|
||||||
|
index 325a5452..4eea9f58 100644
|
||||||
|
--- a/pagure/lib/model.py
|
||||||
|
+++ b/pagure/lib/model.py
|
||||||
|
@@ -487,6 +487,16 @@ class Project(BASE):
|
||||||
|
)
|
||||||
|
|
||||||
|
collaborator_groups = relation(
|
||||||
|
+ "PagureGroup",
|
||||||
|
+ secondary="projects_groups",
|
||||||
|
+ primaryjoin="projects.c.id==projects_groups.c.project_id",
|
||||||
|
+ secondaryjoin="and_(pagure_group.c.id==projects_groups.c.group_id,\
|
||||||
|
+ projects_groups.c.access=='collaborator')",
|
||||||
|
+ order_by="PagureGroup.group_name.asc()",
|
||||||
|
+ viewonly=True,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ collaborator_project_groups = relation(
|
||||||
|
"ProjectGroup",
|
||||||
|
primaryjoin="and_(projects.c.id==projects_groups.c.project_id,\
|
||||||
|
projects_groups.c.access=='collaborator')",
|
||||||
|
diff --git a/pagure/utils.py b/pagure/utils.py
|
||||||
|
index 24a0ce4d..915ba499 100644
|
||||||
|
--- a/pagure/utils.py
|
||||||
|
+++ b/pagure/utils.py
|
||||||
|
@@ -311,7 +311,7 @@ def is_repo_collaborator(repo_obj, refname, username=None, session=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If they are in a group that has commit access -> maybe
|
||||||
|
- for project_group in repo_obj.collaborator_groups:
|
||||||
|
+ for project_group in repo_obj.collaborator_project_groups:
|
||||||
|
if project_group.group.group_name in usergroups:
|
||||||
|
# if branch is None when the user tries to read,
|
||||||
|
# so we'll allow that
|
||||||
|
diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py
|
||||||
|
index 3c364be2..51dd8e9f 100644
|
||||||
|
--- a/tests/test_pagure_flask_api_project.py
|
||||||
|
+++ b/tests/test_pagure_flask_api_project.py
|
||||||
|
@@ -1010,6 +1010,27 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
|
||||||
|
)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
+ # Add a collaborator group
|
||||||
|
+ msg = pagure.lib.query.add_group(
|
||||||
|
+ self.session,
|
||||||
|
+ group_name="some_group",
|
||||||
|
+ display_name="Some Group",
|
||||||
|
+ description=None,
|
||||||
|
+ group_type="bar",
|
||||||
|
+ user="pingou",
|
||||||
|
+ is_admin=False,
|
||||||
|
+ blacklist=[],
|
||||||
|
+ )
|
||||||
|
+ pagure.lib.query.add_group_to_project(
|
||||||
|
+ session=self.session,
|
||||||
|
+ project=project,
|
||||||
|
+ new_group="some_group",
|
||||||
|
+ user="pingou",
|
||||||
|
+ access="collaborator",
|
||||||
|
+ branches="features/*",
|
||||||
|
+ )
|
||||||
|
+ self.session.commit()
|
||||||
|
+
|
||||||
|
# Existing project
|
||||||
|
output = self.app.get("/api/0/test")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
@@ -1019,7 +1040,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests):
|
||||||
|
expected_data = {
|
||||||
|
"access_groups": {
|
||||||
|
"admin": [],
|
||||||
|
- "collaborator": [],
|
||||||
|
+ "collaborator": ["some_group"],
|
||||||
|
"commit": [],
|
||||||
|
"ticket": [],
|
||||||
|
},
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
219
0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
Normal file
219
0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
From 3f65d123faa3a1fcd0b93921e5d42fe659b79fa7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
Date: Wed, 12 Aug 2020 21:33:07 +0200
|
||||||
|
Subject: [PATCH 6/9] When a file a detected as a binary file, return the raw
|
||||||
|
file
|
||||||
|
|
||||||
|
Basically, with the code until now, if an user was trying to view
|
||||||
|
a binary file in the UI, it was then prompted to download the file
|
||||||
|
(as pagure doesn't know how to display binary file), but the file
|
||||||
|
the users were downloading wasn't the raw file but rather the html
|
||||||
|
page that would contain the file.
|
||||||
|
Not ideal.
|
||||||
|
|
||||||
|
So with this commit we're now just saying: if the file is binary and
|
||||||
|
we can't render it, just return the raw file to the user and let
|
||||||
|
them deal with it.
|
||||||
|
|
||||||
|
Fixes https://pagure.io/pagure/issue/4907
|
||||||
|
|
||||||
|
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
---
|
||||||
|
pagure/ui/repo.py | 8 +++-
|
||||||
|
tests/test_pagure_flask_ui_fork.py | 18 ++-------
|
||||||
|
tests/test_pagure_flask_ui_repo.py | 25 ++++---------
|
||||||
|
tests/test_pagure_flask_ui_repo_view_file.py | 39 +++++++++-----------
|
||||||
|
4 files changed, 35 insertions(+), 55 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py
|
||||||
|
index b6aacc8e..06afb71d 100644
|
||||||
|
--- a/pagure/ui/repo.py
|
||||||
|
+++ b/pagure/ui/repo.py
|
||||||
|
@@ -639,7 +639,13 @@ def view_file(repo, identifier, filename, username=None, namespace=None):
|
||||||
|
output_type = "tree"
|
||||||
|
|
||||||
|
if output_type == "binary":
|
||||||
|
- headers[str("Content-Disposition")] = "attachment"
|
||||||
|
+ return view_raw_file(
|
||||||
|
+ repo,
|
||||||
|
+ identifier,
|
||||||
|
+ filename=filename,
|
||||||
|
+ username=username,
|
||||||
|
+ namespace=namespace,
|
||||||
|
+ )
|
||||||
|
|
||||||
|
return flask.Response(
|
||||||
|
flask.stream_with_context(
|
||||||
|
diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py
|
||||||
|
index 8e8dce1c..1bff134f 100644
|
||||||
|
--- a/tests/test_pagure_flask_ui_fork.py
|
||||||
|
+++ b/tests/test_pagure_flask_ui_fork.py
|
||||||
|
@@ -4676,10 +4676,7 @@ More information</textarea>
|
||||||
|
# Check fork-edit doesn't show for binary files
|
||||||
|
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- self.assertNotIn(
|
||||||
|
- "Fork and Edit\n </button>\n",
|
||||||
|
- output.get_data(as_text=True),
|
||||||
|
- )
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
# Check for edit panel
|
||||||
|
output = self.app.post(
|
||||||
|
@@ -4737,8 +4734,7 @@ More information</textarea>
|
||||||
|
)
|
||||||
|
self.assertEqual(output.status_code, 400)
|
||||||
|
self.assertIn(
|
||||||
|
- "<p>Cannot edit binary files</p>",
|
||||||
|
- output.get_data(as_text=True),
|
||||||
|
+ b"<p>Cannot edit binary files</p>", output.data,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check fork-edit shows when user is not logged in
|
||||||
|
@@ -4764,10 +4760,7 @@ More information</textarea>
|
||||||
|
# Check fork-edit doesn't show for binary
|
||||||
|
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- self.assertNotIn(
|
||||||
|
- "Edit in your fork\n </button>\n",
|
||||||
|
- output.get_data(as_text=True),
|
||||||
|
- )
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
@patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
|
||||||
|
def test_fork_edit_file_namespace(self):
|
||||||
|
@@ -4865,10 +4858,7 @@ More information</textarea>
|
||||||
|
"/somenamespace/test3/blob/master/f/test.jpg"
|
||||||
|
)
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- self.assertNotIn(
|
||||||
|
- "Fork and Edit\n </button>\n",
|
||||||
|
- output.get_data(as_text=True),
|
||||||
|
- )
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
# Check for edit panel
|
||||||
|
output = self.app.post(
|
||||||
|
diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py
|
||||||
|
index 27bf6e65..b4322e7d 100644
|
||||||
|
--- a/tests/test_pagure_flask_ui_repo.py
|
||||||
|
+++ b/tests/test_pagure_flask_ui_repo.py
|
||||||
|
@@ -2592,12 +2592,7 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
# View what's supposed to be an image
|
||||||
|
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
- self.assertIn(
|
||||||
|
- '<a href="/test/raw/master/f/test.jpg">view the raw version',
|
||||||
|
- output_text,
|
||||||
|
- )
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
# View by commit id
|
||||||
|
repo = pygit2.Repository(os.path.join(self.path, "repos", "test.git"))
|
||||||
|
@@ -2605,23 +2600,17 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
|
||||||
|
output = self.app.get("/test/blob/%s/f/test.jpg" % commit.oid.hex)
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
# View by image name -- somehow we support this
|
||||||
|
- output = self.app.get("/test/blob/sources/f/test.jpg")
|
||||||
|
+ output = self.app.get("/test/blob/master/f/test.jpg")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
# View binary file
|
||||||
|
- output = self.app.get("/test/blob/sources/f/test_binary")
|
||||||
|
+ output = self.app.get("/test/blob/master/f/test_binary")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn('/f/test_binary">view the raw version', output_text)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
# View folder
|
||||||
|
output = self.app.get("/test/blob/master/f/folder1")
|
||||||
|
@@ -2748,7 +2737,7 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
output = self.app.get("/test/blob/master/f/sources")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
+ self.assertEqual("foo\n bar", output_text)
|
||||||
|
|
||||||
|
def test_view_raw_file(self):
|
||||||
|
""" Test the view_raw_file endpoint. """
|
||||||
|
diff --git a/tests/test_pagure_flask_ui_repo_view_file.py b/tests/test_pagure_flask_ui_repo_view_file.py
|
||||||
|
index 16a1ce18..effa06b6 100644
|
||||||
|
--- a/tests/test_pagure_flask_ui_repo_view_file.py
|
||||||
|
+++ b/tests/test_pagure_flask_ui_repo_view_file.py
|
||||||
|
@@ -135,12 +135,7 @@ class PagureFlaskRepoViewFiletests(LocalBasetests):
|
||||||
|
# View what's supposed to be an image
|
||||||
|
output = self.app.get("/test/blob/master/f/test.jpg")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
- self.assertIn(
|
||||||
|
- '<a href="/test/raw/master/f/test.jpg">view the raw version',
|
||||||
|
- output_text,
|
||||||
|
- )
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
def test_view_file_by_commit(self):
|
||||||
|
""" Test the view_file in a specific commit. """
|
||||||
|
@@ -151,29 +146,29 @@ class PagureFlaskRepoViewFiletests(LocalBasetests):
|
||||||
|
|
||||||
|
output = self.app.get("/test/blob/%s/f/test.jpg" % commit.oid.hex)
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
- def test_view_file_by_name(self):
|
||||||
|
+ def test_view_file_invalid_branch(self):
|
||||||
|
""" Test the view_file via a image name. """
|
||||||
|
-
|
||||||
|
- # View by image name -- somehow we support this
|
||||||
|
output = self.app.get("/test/blob/sources/f/test.jpg")
|
||||||
|
- self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn("Binary files cannot be rendered.<br/>", output_text)
|
||||||
|
- self.assertIn('/f/test.jpg">view the raw version', output_text)
|
||||||
|
+ self.assertEqual(output.status_code, 404)
|
||||||
|
|
||||||
|
- def test_view_file_binary_file2(self):
|
||||||
|
+ def test_view_file_invalid_branch2(self):
|
||||||
|
""" Test the view_file with a binary file (2). """
|
||||||
|
-
|
||||||
|
- # View binary file
|
||||||
|
output = self.app.get("/test/blob/sources/f/test_binary")
|
||||||
|
+ self.assertEqual(output.status_code, 404)
|
||||||
|
+
|
||||||
|
+ def test_view_file_invalid_branch(self):
|
||||||
|
+ """ Test the view_file via a image name. """
|
||||||
|
+ output = self.app.get("/test/blob/master/f/test.jpg")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
- output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertIn('/f/test_binary">view the raw version', output_text)
|
||||||
|
- self.assertTrue("Binary files cannot be rendered.<br/>" in output_text)
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
+
|
||||||
|
+ def test_view_file_invalid_branch2(self):
|
||||||
|
+ """ Test the view_file with a binary file (2). """
|
||||||
|
+ output = self.app.get("/test/blob/master/f/test_binary")
|
||||||
|
+ self.assertEqual(output.status_code, 200)
|
||||||
|
+ self.assertNotIn(b"<html", output.data)
|
||||||
|
|
||||||
|
def test_view_file_for_folder(self):
|
||||||
|
""" Test the view_file with a folder. """
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
86
0007-Remove-fenced-code-block-when-checking-mention.patch
Normal file
86
0007-Remove-fenced-code-block-when-checking-mention.patch
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
From e921f23f8135d3e6667d532e06504f520b8c0109 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Scherer <misc@redhat.com>
|
||||||
|
Date: Thu, 3 Sep 2020 16:44:20 +0200
|
||||||
|
Subject: [PATCH 7/9] Remove fenced code block when checking mention
|
||||||
|
|
||||||
|
Fix bug #4978
|
||||||
|
|
||||||
|
We have to remove code using the '~~~~' markup since
|
||||||
|
this result in incorrect trigger, especially on private
|
||||||
|
ticket.
|
||||||
|
---
|
||||||
|
pagure/lib/notify.py | 6 +++++-
|
||||||
|
tests/test_pagure_lib_notify.py | 26 ++++++++++++++++++++++++++
|
||||||
|
2 files changed, 31 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py
|
||||||
|
index 0c124db9..02c277c0 100644
|
||||||
|
--- a/pagure/lib/notify.py
|
||||||
|
+++ b/pagure/lib/notify.py
|
||||||
|
@@ -35,6 +35,7 @@ import pagure.lib.query
|
||||||
|
import pagure.lib.tasks_services
|
||||||
|
from pagure.config import config as pagure_config
|
||||||
|
from pagure.pfmarkdown import MENTION_RE
|
||||||
|
+from markdown.extensions.fenced_code import FencedBlockPreprocessor
|
||||||
|
|
||||||
|
|
||||||
|
_log = logging.getLogger(__name__)
|
||||||
|
@@ -234,7 +235,10 @@ def _add_mentioned_users(emails, comment):
|
||||||
|
""" Check the comment to see if an user is mentioned in it and if
|
||||||
|
so add this user to the list of people to notify.
|
||||||
|
"""
|
||||||
|
- for username in re.findall(MENTION_RE, comment):
|
||||||
|
+ filtered_comment = re.sub(
|
||||||
|
+ FencedBlockPreprocessor.FENCED_BLOCK_RE, "", comment
|
||||||
|
+ )
|
||||||
|
+ for username in re.findall(MENTION_RE, filtered_comment):
|
||||||
|
user = pagure.lib.query.search_user(flask.g.session, username=username)
|
||||||
|
if user:
|
||||||
|
emails.add(user.default_email)
|
||||||
|
diff --git a/tests/test_pagure_lib_notify.py b/tests/test_pagure_lib_notify.py
|
||||||
|
index 8d31cb70..78af57af 100644
|
||||||
|
--- a/tests/test_pagure_lib_notify.py
|
||||||
|
+++ b/tests/test_pagure_lib_notify.py
|
||||||
|
@@ -25,6 +25,7 @@ import pagure.lib.model
|
||||||
|
import pagure.lib.notify
|
||||||
|
import pagure.lib.query
|
||||||
|
import tests
|
||||||
|
+import munch
|
||||||
|
|
||||||
|
|
||||||
|
class PagureLibNotifytests(tests.Modeltests):
|
||||||
|
@@ -543,6 +544,31 @@ RW1haWwgY29udGVudA==
|
||||||
|
"""
|
||||||
|
self.assertEqual(email.as_string(), exp)
|
||||||
|
|
||||||
|
+ def test_notification_mention(self):
|
||||||
|
+ g = munch.Munch()
|
||||||
|
+ g.session = self.session
|
||||||
|
+ with patch("flask.g", g):
|
||||||
|
+
|
||||||
|
+ def _check_mention(comment, exp):
|
||||||
|
+ emails = set([])
|
||||||
|
+ emails = pagure.lib.notify._add_mentioned_users(
|
||||||
|
+ emails, comment
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ self.assertEqual(emails, exp)
|
||||||
|
+
|
||||||
|
+ exp = set(["bar@pingou.com"])
|
||||||
|
+ comment = "I think we should ask @pingou how to pronounce pagure"
|
||||||
|
+ _check_mention(comment, exp)
|
||||||
|
+
|
||||||
|
+ exp = set([])
|
||||||
|
+ comment = """Let me quote him:
|
||||||
|
+~~~~
|
||||||
|
+ @pingou> Pagure is pronounced 'pa-gure', not 'pagu-re'
|
||||||
|
+~~~~
|
||||||
|
+"""
|
||||||
|
+ _check_mention(comment, exp)
|
||||||
|
+
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main(verbosity=2)
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
284
0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
Normal file
284
0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
From a8b2e001d6f4d2e4683aa65d6331b971f8e2ce33 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
Date: Mon, 14 Sep 2020 16:03:31 +0200
|
||||||
|
Subject: [PATCH 8/9] Add support for using cchardet to detect files' encoding
|
||||||
|
|
||||||
|
cchardet is a much faster version of the chardet library that can
|
||||||
|
be used to automatically detect the encoding of a file.
|
||||||
|
|
||||||
|
Since this library is only available on python3, we're making it
|
||||||
|
an optional dependency for now.
|
||||||
|
|
||||||
|
Fixes https://pagure.io/pagure/issue/4977
|
||||||
|
|
||||||
|
Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
|
||||||
|
---
|
||||||
|
pagure/lib/encoding_utils.py | 12 ++++-
|
||||||
|
tests/test_pagure_flask_ui_repo.py | 58 ++++++++++++++++++++-----
|
||||||
|
tests/test_pagure_lib_encoding_utils.py | 40 ++++++++++++-----
|
||||||
|
tests/test_pagure_lib_mimetype.py | 28 ++++++++++--
|
||||||
|
4 files changed, 111 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pagure/lib/encoding_utils.py b/pagure/lib/encoding_utils.py
|
||||||
|
index 66f7dced..304e7d84 100644
|
||||||
|
--- a/pagure/lib/encoding_utils.py
|
||||||
|
+++ b/pagure/lib/encoding_utils.py
|
||||||
|
@@ -15,7 +15,12 @@ from __future__ import unicode_literals, division, absolute_import
|
||||||
|
from collections import namedtuple
|
||||||
|
import logging
|
||||||
|
|
||||||
|
-from chardet import universaldetector, __version__ as ch_version
|
||||||
|
+try:
|
||||||
|
+ import cchardet
|
||||||
|
+ from cchardet import __version__ as ch_version
|
||||||
|
+except ImportError:
|
||||||
|
+ cchardet = None
|
||||||
|
+ from chardet import universaldetector, __version__ as ch_version
|
||||||
|
|
||||||
|
from pagure.exceptions import PagureEncodingException
|
||||||
|
|
||||||
|
@@ -44,7 +49,10 @@ def detect_encodings(data):
|
||||||
|
|
||||||
|
# We can't use ``chardet.detect`` because we want to dig in the internals
|
||||||
|
# of the detector to bias the utf-8 result.
|
||||||
|
- detector = universaldetector.UniversalDetector()
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ detector = cchardet.UniversalDetector()
|
||||||
|
+ else:
|
||||||
|
+ detector = universaldetector.UniversalDetector()
|
||||||
|
detector.reset()
|
||||||
|
detector.feed(data)
|
||||||
|
result = detector.close()
|
||||||
|
diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py
|
||||||
|
index b4322e7d..e816e7f7 100644
|
||||||
|
--- a/tests/test_pagure_flask_ui_repo.py
|
||||||
|
+++ b/tests/test_pagure_flask_ui_repo.py
|
||||||
|
@@ -20,6 +20,12 @@ import tempfile
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
+cchardet = None
|
||||||
|
+try:
|
||||||
|
+ import cchardet
|
||||||
|
+except ImportError:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
import pygit2
|
||||||
|
import six
|
||||||
|
from mock import ANY, patch, MagicMock
|
||||||
|
@@ -2763,9 +2769,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
output = self.app.get("/test/raw/master")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertEqual(
|
||||||
|
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||||
|
- )
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=utf-8",
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=ascii",
|
||||||
|
+ )
|
||||||
|
self.assertIn(":Author: Pierre-Yves Chibon", output_text)
|
||||||
|
|
||||||
|
# Add some more content to the repo
|
||||||
|
@@ -2784,9 +2797,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
|
||||||
|
# View in a branch
|
||||||
|
output = self.app.get("/test/raw/master/f/sources")
|
||||||
|
- self.assertEqual(
|
||||||
|
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||||
|
- )
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=utf-8",
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=ascii",
|
||||||
|
+ )
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
output_text = output.get_data(as_text=True)
|
||||||
|
self.assertIn("foo\n bar", output_text)
|
||||||
|
@@ -2837,9 +2857,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
output = self.app.get("/test/raw/master")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertEqual(
|
||||||
|
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||||
|
- )
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=utf-8",
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=ascii",
|
||||||
|
+ )
|
||||||
|
self.assertTrue(
|
||||||
|
output_text.startswith("diff --git a/test_binary b/test_binary\n")
|
||||||
|
)
|
||||||
|
@@ -2877,9 +2904,16 @@ class PagureFlaskRepotests(tests.Modeltests):
|
||||||
|
output = self.app.get("/fork/pingou/test3/raw/master/f/sources")
|
||||||
|
self.assertEqual(output.status_code, 200)
|
||||||
|
output_text = output.get_data(as_text=True)
|
||||||
|
- self.assertEqual(
|
||||||
|
- output.headers["Content-Type"].lower(), "text/plain; charset=ascii"
|
||||||
|
- )
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=utf-8",
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ output.headers["Content-Type"].lower(),
|
||||||
|
+ "text/plain; charset=ascii",
|
||||||
|
+ )
|
||||||
|
self.assertIn("foo\n bar", output_text)
|
||||||
|
|
||||||
|
def test_view_commit(self):
|
||||||
|
diff --git a/tests/test_pagure_lib_encoding_utils.py b/tests/test_pagure_lib_encoding_utils.py
|
||||||
|
index ccc8825f..aff7d8ba 100644
|
||||||
|
--- a/tests/test_pagure_lib_encoding_utils.py
|
||||||
|
+++ b/tests/test_pagure_lib_encoding_utils.py
|
||||||
|
@@ -5,11 +5,18 @@ Tests for :module:`pagure.lib.encoding_utils`.
|
||||||
|
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
-import chardet
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
+cchardet = None
|
||||||
|
+try:
|
||||||
|
+ import cchardet
|
||||||
|
+except ImportError:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+import chardet
|
||||||
|
+
|
||||||
|
sys.path.insert(
|
||||||
|
0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
||||||
|
)
|
||||||
|
@@ -24,7 +31,10 @@ class TestGuessEncoding(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
data = "Twas bryllyg, and the slythy toves did gyre and gymble"
|
||||||
|
result = encoding_utils.guess_encoding(data.encode("ascii"))
|
||||||
|
- self.assertEqual(result, "ascii")
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ self.assertEqual(result, "utf-8")
|
||||||
|
+ else:
|
||||||
|
+ self.assertEqual(result, "ascii")
|
||||||
|
|
||||||
|
def test_guess_encoding_favor_utf_8(self):
|
||||||
|
"""
|
||||||
|
@@ -56,17 +66,24 @@ class TestGuessEncodings(unittest.TestCase):
|
||||||
|
chardet_result = chardet.detect(data)
|
||||||
|
if chardet.__version__[0] == "3":
|
||||||
|
# The first three have different confidence values
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ expexted_list = ["utf-8"]
|
||||||
|
+ # The last one in the list (which apparently has only one)
|
||||||
|
+ self.assertEqual(result[-1].encoding, "utf-8")
|
||||||
|
+ else:
|
||||||
|
+ expexted_list = ["utf-8", "ISO-8859-9", "ISO-8859-1"]
|
||||||
|
+ # This is the one with the least confidence
|
||||||
|
+ self.assertEqual(result[-1].encoding, "windows-1255")
|
||||||
|
self.assertListEqual(
|
||||||
|
- [encoding.encoding for encoding in result][:3],
|
||||||
|
- ["utf-8", "ISO-8859-9", "ISO-8859-1"],
|
||||||
|
+ [encoding.encoding for encoding in result][:3], expexted_list
|
||||||
|
)
|
||||||
|
- # This is the one with the least confidence
|
||||||
|
- self.assertEqual(result[-1].encoding, "windows-1255")
|
||||||
|
+
|
||||||
|
# The values in the middle of the list all have the same confidence
|
||||||
|
# value and can't be sorted reliably: use sets.
|
||||||
|
- self.assertEqual(
|
||||||
|
- set([encoding.encoding for encoding in result]),
|
||||||
|
- set(
|
||||||
|
+ if cchardet is not None:
|
||||||
|
+ expected_list = sorted(["utf-8"])
|
||||||
|
+ else:
|
||||||
|
+ expected_list = sorted(
|
||||||
|
[
|
||||||
|
"utf-8",
|
||||||
|
"ISO-8859-9",
|
||||||
|
@@ -89,7 +106,10 @@ class TestGuessEncodings(unittest.TestCase):
|
||||||
|
"windows-1251",
|
||||||
|
"windows-1255",
|
||||||
|
]
|
||||||
|
- ),
|
||||||
|
+ )
|
||||||
|
+ self.assertListEqual(
|
||||||
|
+ sorted(set([encoding.encoding for encoding in result])),
|
||||||
|
+ expected_list,
|
||||||
|
)
|
||||||
|
self.assertEqual(chardet_result["encoding"], "ISO-8859-9")
|
||||||
|
else:
|
||||||
|
diff --git a/tests/test_pagure_lib_mimetype.py b/tests/test_pagure_lib_mimetype.py
|
||||||
|
index d5947bee..8c2f4a31 100644
|
||||||
|
--- a/tests/test_pagure_lib_mimetype.py
|
||||||
|
+++ b/tests/test_pagure_lib_mimetype.py
|
||||||
|
@@ -9,6 +9,12 @@ import os
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
+cchardet = None
|
||||||
|
+try:
|
||||||
|
+ import cchardet
|
||||||
|
+except ImportError:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
from pagure.lib import mimetype
|
||||||
|
|
||||||
|
sys.path.insert(
|
||||||
|
@@ -20,8 +26,18 @@ class TestMIMEType(unittest.TestCase):
|
||||||
|
def test_guess_type(self):
|
||||||
|
dataset = [
|
||||||
|
("hello.html", None, "text/html", None),
|
||||||
|
- ("hello.html", b"#!", "text/html", "ascii"),
|
||||||
|
- ("hello", b"#!", "text/plain", "ascii"),
|
||||||
|
+ (
|
||||||
|
+ "hello.html",
|
||||||
|
+ b"#!",
|
||||||
|
+ "text/html",
|
||||||
|
+ "ascii" if cchardet is None else "utf-8",
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ "hello",
|
||||||
|
+ b"#!",
|
||||||
|
+ "text/plain",
|
||||||
|
+ "ascii" if cchardet is None else "utf-8",
|
||||||
|
+ ),
|
||||||
|
("hello.jpg", None, "image/jpeg", None),
|
||||||
|
("hello.jpg", b"#!", "image/jpeg", None),
|
||||||
|
("hello.jpg", b"\0", "image/jpeg", None),
|
||||||
|
@@ -49,7 +65,13 @@ class TestMIMEType(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_get_normal_headers(self):
|
||||||
|
dataset = [
|
||||||
|
- ("hello", b"#!", "text/plain; charset=ascii"),
|
||||||
|
+ (
|
||||||
|
+ "hello",
|
||||||
|
+ b"#!",
|
||||||
|
+ "text/plain; charset=ascii"
|
||||||
|
+ if cchardet is None
|
||||||
|
+ else "text/plain; charset=utf-8",
|
||||||
|
+ ),
|
||||||
|
("hello.jpg", None, "image/jpeg"),
|
||||||
|
("hello.jpg", b"#!", "image/jpeg"),
|
||||||
|
("hello.jpg", b"\0", "image/jpeg"),
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
134
0009-Add-support-for-disabling-user-registration.patch
Normal file
134
0009-Add-support-for-disabling-user-registration.patch
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
From 8e23c79fb64d4dd4e6f17f809d7e629840f7e91c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Neal Gompa <ngompa13@gmail.com>
|
||||||
|
Date: Thu, 24 Sep 2020 06:40:06 -0400
|
||||||
|
Subject: [PATCH 9/9] Add support for disabling user registration
|
||||||
|
|
||||||
|
For public/private Pagure instances where it is intended to be used
|
||||||
|
by a single user, having the ability to turn off user registration
|
||||||
|
prevents confusion and closes an avenue of potential denial of service
|
||||||
|
attacks.
|
||||||
|
|
||||||
|
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
|
||||||
|
---
|
||||||
|
doc/configuration.rst | 13 +++++++++++++
|
||||||
|
pagure/default_config.py | 3 +++
|
||||||
|
pagure/templates/login/login.html | 2 ++
|
||||||
|
pagure/ui/login.py | 3 +++
|
||||||
|
tests/test_pagure_flask_ui_login.py | 24 ++++++++++++++++++++++++
|
||||||
|
5 files changed, 45 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/doc/configuration.rst b/doc/configuration.rst
|
||||||
|
index 735e378c..2ea7a66d 100644
|
||||||
|
--- a/doc/configuration.rst
|
||||||
|
+++ b/doc/configuration.rst
|
||||||
|
@@ -1117,6 +1117,7 @@ Valid options are ``fas``, ``openid``, ``oidc``, or ``local``.
|
||||||
|
the configuration options starting with ``OIDC_`` (see below) to be provided.
|
||||||
|
|
||||||
|
* ``local`` causes pagure to use the local pagure database for user management.
|
||||||
|
+ User registration can be disabled with the ALLOW_USER_REGISTRATION configuration key.
|
||||||
|
|
||||||
|
Defaults to: ``local``.
|
||||||
|
|
||||||
|
@@ -1784,6 +1785,18 @@ If turned off, users are managed outside of pagure.
|
||||||
|
Defaults to: ``True``
|
||||||
|
|
||||||
|
|
||||||
|
+ALLOW_USER_REGISTRATION
|
||||||
|
+~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
+
|
||||||
|
+This configuration key can be used to turn on or off user registration
|
||||||
|
+(that is, the ability for users to create an account) in this pagure instance.
|
||||||
|
+If turned off, user accounts cannot be created through the UI or API.
|
||||||
|
+Currently, this key only applies to pagure instances configured with the ``local``
|
||||||
|
+authentication backend and has no effect with the other authentication backends.
|
||||||
|
+
|
||||||
|
+Defaults to: ``True``
|
||||||
|
+
|
||||||
|
+
|
||||||
|
SESSION_COOKIE_NAME
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
diff --git a/pagure/default_config.py b/pagure/default_config.py
|
||||||
|
index 045f2704..df0cd6b0 100644
|
||||||
|
--- a/pagure/default_config.py
|
||||||
|
+++ b/pagure/default_config.py
|
||||||
|
@@ -78,6 +78,9 @@ ENABLE_GROUP_MNGT = True
|
||||||
|
# Enables / Disables private projects
|
||||||
|
PRIVATE_PROJECTS = True
|
||||||
|
|
||||||
|
+# Enable / Disable user registration (local auth only)
|
||||||
|
+ALLOW_USER_REGISTRATION = True
|
||||||
|
+
|
||||||
|
# Enable / Disable deleting branches in the UI
|
||||||
|
ALLOW_DELETE_BRANCH = True
|
||||||
|
|
||||||
|
diff --git a/pagure/templates/login/login.html b/pagure/templates/login/login.html
|
||||||
|
index a65b10ae..e209c400 100644
|
||||||
|
--- a/pagure/templates/login/login.html
|
||||||
|
+++ b/pagure/templates/login/login.html
|
||||||
|
@@ -18,11 +18,13 @@
|
||||||
|
<input class="btn btn-primary btn-block mt-4" type="submit" value="Login">
|
||||||
|
{{ form.csrf_token }}
|
||||||
|
</form>
|
||||||
|
+ {% if config.get('ALLOW_USER_REGISTRATION', True) %}
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-link btn-block" href="{{url_for('ui_ns.new_user') }}">
|
||||||
|
Create a new account
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
+ {% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
diff --git a/pagure/ui/login.py b/pagure/ui/login.py
|
||||||
|
index 1a0dbd24..7da94a37 100644
|
||||||
|
--- a/pagure/ui/login.py
|
||||||
|
+++ b/pagure/ui/login.py
|
||||||
|
@@ -38,6 +38,9 @@ _log = logging.getLogger(__name__)
|
||||||
|
def new_user():
|
||||||
|
""" Create a new user.
|
||||||
|
"""
|
||||||
|
+ if not pagure.config.config.get("ALLOW_USER_REGISTRATION", True):
|
||||||
|
+ flask.flash("User registration is disabled.", "error")
|
||||||
|
+ return flask.redirect(flask.url_for("auth_login"))
|
||||||
|
form = forms.NewUserForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
|
||||||
|
diff --git a/tests/test_pagure_flask_ui_login.py b/tests/test_pagure_flask_ui_login.py
|
||||||
|
index f11a2b22..8a1d16c7 100644
|
||||||
|
--- a/tests/test_pagure_flask_ui_login.py
|
||||||
|
+++ b/tests/test_pagure_flask_ui_login.py
|
||||||
|
@@ -149,6 +149,30 @@ class PagureFlaskLogintests(tests.SimplePagureTest):
|
||||||
|
items = pagure.lib.query.search_user(self.session)
|
||||||
|
self.assertEqual(3, len(items))
|
||||||
|
|
||||||
|
+ @patch.dict("pagure.config.config", {"PAGURE_AUTH": "local"})
|
||||||
|
+ @patch.dict("pagure.config.config", {"ALLOW_USER_REGISTRATION": False})
|
||||||
|
+ @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
|
||||||
|
+ def test_new_user_disabled(self):
|
||||||
|
+ """ Test the disabling of the new_user endpoint. """
|
||||||
|
+
|
||||||
|
+ # Check before:
|
||||||
|
+ items = pagure.lib.query.search_user(self.session)
|
||||||
|
+ self.assertEqual(2, len(items))
|
||||||
|
+
|
||||||
|
+ # Attempt to access the new user page
|
||||||
|
+ output = self.app.get("/user/new", follow_redirects=True)
|
||||||
|
+ self.assertEqual(output.status_code, 200)
|
||||||
|
+ self.assertIn(
|
||||||
|
+ "<title>Login - Pagure</title>", output.get_data(as_text=True)
|
||||||
|
+ )
|
||||||
|
+ self.assertIn(
|
||||||
|
+ "User registration is disabled.", output.get_data(as_text=True)
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ # Check after:
|
||||||
|
+ items = pagure.lib.query.search_user(self.session)
|
||||||
|
+ self.assertEqual(2, len(items))
|
||||||
|
+
|
||||||
|
@patch.dict("pagure.config.config", {"PAGURE_AUTH": "local"})
|
||||||
|
@patch.dict("pagure.config.config", {"CHECK_SESSION_IP": False})
|
||||||
|
def test_do_login(self):
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -1,3 +1,18 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Sep 24 22:57:42 UTC 2020 - Neal Gompa <ngompa13@gmail.com>
|
||||||
|
|
||||||
|
- Backport various fixes from upstream
|
||||||
|
+ Patch: 0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
|
||||||
|
+ Patch: 0002-Show-the-assignee-s-avatar-on-the-board.patch
|
||||||
|
+ Patch: 0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
|
||||||
|
+ Patch: 0004-Include-the-assignee-in-the-list-of-people-notified-.patch
|
||||||
|
+ Patch: 0005-Introduce-the-collaborator_project_groups-mapping.patch
|
||||||
|
+ Patch: 0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
|
||||||
|
+ Patch: 0007-Remove-fenced-code-block-when-checking-mention.patch
|
||||||
|
+ Patch: 0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
|
||||||
|
+ Patch: 0009-Add-support-for-disabling-user-registration.patch
|
||||||
|
- Remove mandatory dependency on systemd to ease containerization
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Sun Aug 30 14:25:21 UTC 2020 - Neal Gompa <ngompa13@gmail.com>
|
Sun Aug 30 14:25:21 UTC 2020 - Neal Gompa <ngompa13@gmail.com>
|
||||||
|
|
||||||
|
17
pagure.spec
17
pagure.spec
@ -41,6 +41,18 @@ Source1: https://raw.githubusercontent.com/fedora-infra/python-fedora
|
|||||||
Source10: pagure-README.SUSE
|
Source10: pagure-README.SUSE
|
||||||
|
|
||||||
|
|
||||||
|
# Backports from upstream
|
||||||
|
Patch0001: 0001-Display-real-line-numbers-on-pull-request-s-diff-vie.patch
|
||||||
|
Patch0002: 0002-Show-the-assignee-s-avatar-on-the-board.patch
|
||||||
|
Patch0003: 0003-Allow-setting-a-status-as-closing-even-if-the-projec.patch
|
||||||
|
Patch0004: 0004-Include-the-assignee-in-the-list-of-people-notified-.patch
|
||||||
|
Patch0005: 0005-Introduce-the-collaborator_project_groups-mapping.patch
|
||||||
|
Patch0006: 0006-When-a-file-a-detected-as-a-binary-file-return-the-r.patch
|
||||||
|
Patch0007: 0007-Remove-fenced-code-block-when-checking-mention.patch
|
||||||
|
Patch0008: 0008-Add-support-for-using-cchardet-to-detect-files-encod.patch
|
||||||
|
Patch0009: 0009-Add-support-for-disabling-user-registration.patch
|
||||||
|
|
||||||
|
|
||||||
# SUSE-specific fixes
|
# SUSE-specific fixes
|
||||||
## Change the defaults in the example config to match packaging
|
## Change the defaults in the example config to match packaging
|
||||||
Patch1000: pagure-5.0-default-example-cfg.patch
|
Patch1000: pagure-5.0-default-example-cfg.patch
|
||||||
@ -122,6 +134,9 @@ Requires: python3-dbm
|
|||||||
Requires: python3-kitchen
|
Requires: python3-kitchen
|
||||||
Requires: python3-requests
|
Requires: python3-requests
|
||||||
|
|
||||||
|
# We want to use cchardet whenever it's available
|
||||||
|
Recommends: python3-cchardet
|
||||||
|
|
||||||
# If using PostgreSQL, the correct driver should be installed
|
# If using PostgreSQL, the correct driver should be installed
|
||||||
Recommends: (python3-psycopg2 if postgresql-server)
|
Recommends: (python3-psycopg2 if postgresql-server)
|
||||||
|
|
||||||
@ -137,7 +152,7 @@ Recommends: (%{name}-web-nginx if nginx)
|
|||||||
# The default theme is required
|
# The default theme is required
|
||||||
Requires: %{name}-theme-default
|
Requires: %{name}-theme-default
|
||||||
|
|
||||||
%{?systemd_requires}
|
%{?systemd_ordering}
|
||||||
|
|
||||||
# We use the git tools for some actions due to deficiencies in libgit2 and pygit2
|
# We use the git tools for some actions due to deficiencies in libgit2 and pygit2
|
||||||
Requires: git-core
|
Requires: git-core
|
||||||
|
Loading…
x
Reference in New Issue
Block a user