Compare commits
30 Commits
eda6dd9f3f
...
v25.1.18
Author | SHA1 | Date | |
---|---|---|---|
7bf65b63ff
|
|||
188ead820d | |||
![]() |
e07054c8ea | ||
![]() |
97aae09dce | ||
![]() |
0ce1a0ea5f | ||
![]() |
f38770be76 | ||
![]() |
2d39dc6379 | ||
![]() |
df4b0bfd67 | ||
![]() |
5da7fa80c5 | ||
![]() |
8d495d4fa7 | ||
![]() |
796c3f410f | ||
![]() |
37687bf9e4 | ||
7accacd5fd | |||
10fecc63e9
|
|||
368e248efc | |||
a71b1f783e
|
|||
77531b1948
|
|||
![]() |
2bf2fa235f | ||
![]() |
87a0d37953 | ||
![]() |
4210a46f9a | ||
![]() |
bd4d50b84e | ||
![]() |
fcd473608c | ||
74bfaed558 | |||
![]() |
4e25b014e4 | ||
1a1d963ca4
|
|||
f8d5473c25 | |||
![]() |
c15b22203a | ||
![]() |
b39c4c9385 | ||
43c333727d | |||
![]() |
3da96a4007 |
2
.flake8
2
.flake8
@@ -1,3 +1,3 @@
|
||||
[flake8]
|
||||
max-line-length = 300
|
||||
max-line-length = 118
|
||||
ignore = E731, E241, E741
|
||||
|
2
.github/workflows/build-docker.yml
vendored
2
.github/workflows/build-docker.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
REGISTRY: gitea.artixlinux.org
|
||||
DH_REGISTRY: docker.io
|
||||
REPO_ORG: ${{ gitea.repository_owner }}
|
||||
DH_ORG: corysanin
|
||||
DH_ORG: artixlinux
|
||||
IMAGE_NAME: archweb
|
||||
DH_IMAGE_NAME: archweb
|
||||
ABSOLUTE_IMAGE: ${{ env.REGISTRY }}/${{ env.REPO_ORG }}/${{ env.IMAGE_NAME }}
|
||||
|
9
.github/workflows/main.yml
vendored
9
.github/workflows/main.yml
vendored
@@ -9,14 +9,17 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.11
|
||||
- name: Set up Python 3.13
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.11
|
||||
python-version: 3.13
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt && pip install -r requirements_test.txt
|
||||
pip install -r requirements.txt && pip install -r requirements_test.txt && pip install ruff
|
||||
- name: Run ruff
|
||||
run: |
|
||||
ruff check .
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
make lint
|
||||
|
@@ -1,4 +1,4 @@
|
||||
FROM python:3.12-alpine3.20 AS base
|
||||
FROM python:3.13-alpine3.20 AS base
|
||||
|
||||
RUN apk add --no-cache git gcc musl-dev curl gpg gpg-agent
|
||||
|
||||
|
@@ -71,7 +71,8 @@ class Database(object):
|
||||
retry = False
|
||||
except OperationalError as exc:
|
||||
retry_count += 1
|
||||
logger.error('Unable to update database \'%s\', retrying=%d', self.path, retry_count, exc_info=exc)
|
||||
logger.error('Unable to update database \'%s\', retrying=%d',
|
||||
self.path, retry_count, exc_info=exc)
|
||||
time.sleep(5)
|
||||
|
||||
if retry_count == self.retry_limit:
|
||||
|
@@ -89,7 +89,9 @@ class Command(BaseCommand):
|
||||
for name in all_paths:
|
||||
manager.add_watch(name, mask)
|
||||
|
||||
handler = EventHandler(arch_paths=arch_path_map, filename_suffix='.links.tar.gz', callback_func=wrapper_read_links)
|
||||
handler = EventHandler(arch_paths=arch_path_map,
|
||||
filename_suffix='.links.tar.gz',
|
||||
callback_func=wrapper_read_links)
|
||||
return pyinotify.Notifier(manager, handler)
|
||||
|
||||
|
||||
|
@@ -539,7 +539,9 @@ def parse_info(pkgname, filename, iofile):
|
||||
elif blockname:
|
||||
store[blockname].append(line)
|
||||
else:
|
||||
raise Exception("%s: Read package info outside a block while reading from %s: %s" % (pkgname, filename, line))
|
||||
raise Exception("%s: Read package info outside a block while reading from %s: %s" % (pkgname,
|
||||
filename,
|
||||
line))
|
||||
return store
|
||||
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import zoneinfo
|
||||
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
|
@@ -202,7 +202,8 @@ def non_existing_dependencies(packages):
|
||||
|
||||
|
||||
def non_reproducible_packages(packages):
|
||||
statuses = RebuilderdStatus.objects.select_related().filter(status=RebuilderdStatus.BAD, pkg__pkgname__in=packages.values('pkgname'))
|
||||
statuses = RebuilderdStatus.objects.select_related().filter(status=RebuilderdStatus.BAD,
|
||||
pkg__pkgname__in=packages.values('pkgname'))
|
||||
return linkify_non_reproducible_packages(statuses)
|
||||
|
||||
|
||||
@@ -227,7 +228,7 @@ def orphan_dependencies(packages):
|
||||
JOIN packages_packagerelation ppr ON pp.pkgbase = ppr.pkgbase
|
||||
JOIN (SELECT DISTINCT cp.pkgname FROM packages cp LEFT JOIN packages_packagerelation pr ON cp.pkgbase = pr.pkgbase WHERE pr.id IS NULL) child ON ppd.name = child.pkgname
|
||||
ORDER BY child.pkgname;
|
||||
"""
|
||||
""" # noqa: E501
|
||||
cursor.execute(query)
|
||||
|
||||
for row in cursor.fetchall():
|
||||
|
@@ -216,7 +216,9 @@ def tier0_mirror_auth(request):
|
||||
token = credentials[1]
|
||||
|
||||
groups = Group.objects.filter(name__in=SELECTED_GROUPS)
|
||||
user = User.objects.filter(username=username, is_active=True, groups__in=groups).select_related('userprofile').first()
|
||||
user = User.objects.filter(username=username,
|
||||
is_active=True,
|
||||
groups__in=groups).select_related('userprofile').first()
|
||||
if not user:
|
||||
return unauthorized
|
||||
|
||||
|
@@ -42,4 +42,4 @@ services:
|
||||
ports:
|
||||
- "8080:80"
|
||||
volumes:
|
||||
- ./nginx.conf:/config/nginx/site-confs/default.conf:ro
|
||||
- ./nginx.conf:/config/nginx/site-confs/default.conf
|
@@ -8,7 +8,7 @@ fi
|
||||
|
||||
printf "downloadpackages.sh\nusing %s/\$repo/os/\$arch for mirror.\n" "$mirror"
|
||||
|
||||
repos="system world galaxy lib32 system-gremlins world-gremlins galaxy-gremlins lib32-gremlins"
|
||||
repos="system world galaxy lib32 system-gremlins world-gremlins galaxy-gremlins lib32-gremlins system-goblins world-goblins galaxy-goblins lib32-goblins"
|
||||
|
||||
mkdir -p ./archives
|
||||
|
||||
|
@@ -11,6 +11,18 @@
|
||||
"testing": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 15,
|
||||
"model": "main.repo",
|
||||
"fields": {
|
||||
"bugs_category": 33,
|
||||
"staging": true,
|
||||
"name": "Extra-Staging",
|
||||
"bugs_project": 5,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "main.repo",
|
||||
@@ -118,5 +130,17 @@
|
||||
"svn_root": "packages",
|
||||
"testing": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 16,
|
||||
"model": "main.repo",
|
||||
"fields": {
|
||||
"bugs_category": 10,
|
||||
"staging": true,
|
||||
"name": "Core-Staging",
|
||||
"bugs_project": 1,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -280,7 +280,8 @@ class Package(models.Model):
|
||||
dep_pkgs = list(dep_pkgs)
|
||||
dep = dep_pkgs[0]
|
||||
if len(dep_pkgs) > 1:
|
||||
dep_pkgs = [d for d in dep_pkgs if d.pkg.repo.testing == self.repo.testing and d.pkg.repo.staging == self.repo.staging]
|
||||
dep_pkgs = [d for d in dep_pkgs
|
||||
if d.pkg.repo.testing == self.repo.testing and d.pkg.repo.staging == self.repo.staging]
|
||||
if len(dep_pkgs) > 0:
|
||||
dep = dep_pkgs[0]
|
||||
trimmed.append(dep)
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import cssmin
|
||||
import jsmin
|
||||
from django.contrib.staticfiles.storage import ManifestStaticFilesStorage
|
||||
from django.core.files.base import ContentFile
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
import cssmin
|
||||
|
||||
|
||||
class MinifiedStaticFilesStorage(ManifestStaticFilesStorage):
|
||||
"""
|
||||
|
@@ -35,7 +35,7 @@ def pgp_dev_key_link(key_id):
|
||||
key_id = pad_key_id(key_id)
|
||||
if not key_id:
|
||||
return "Unknown"
|
||||
link_text = (''.join((f'<span>{key_id[i:i+4]}</span>' for i in range(0, len(key_id), 4))))
|
||||
link_text = (''.join((f'<span>{key_id[i:i + 4]}</span>' for i in range(0, len(key_id), 4))))
|
||||
link_text = f'<div class="pgp-key-ids">{link_text}</div>'
|
||||
return pgp_key_link(key_id, link_text)
|
||||
|
||||
@@ -51,7 +51,9 @@ def pgp_key_link(key_id, link_text=None):
|
||||
return format_key(key_id)
|
||||
pgp_server_secure = getattr(settings, 'PGP_SERVER_SECURE', False)
|
||||
scheme = 'https' if pgp_server_secure else 'http'
|
||||
url = '%s://%s/pks/lookup?op=vindex&fingerprint=on&exact=on&search=0x%s' % (scheme, pgp_server, key_id)
|
||||
url = '%s://%s/pks/lookup?op=vindex&fingerprint=on&exact=on&search=0x%s' % (scheme,
|
||||
pgp_server,
|
||||
key_id)
|
||||
if link_text is None:
|
||||
link_text = '0x%s' % key_id[-8:]
|
||||
values = (url, format_key(key_id), link_text)
|
||||
|
@@ -54,10 +54,12 @@ class NewsCreateView(CreateView):
|
||||
if settings.MAILMAN_PASSWORD:
|
||||
headers['Approved'] = settings.MAILMAN_PASSWORD
|
||||
template = loader.get_template('news/news_email_notification.txt')
|
||||
author = newsitem.author.get_full_name()
|
||||
from_ = f'"Arch Linux: Recent news updates: {author}" <{settings.ANNOUNCE_EMAIL}>'
|
||||
EmailMessage(
|
||||
subject=f'[arch-announce] {newsitem.title}',
|
||||
body=template.render(ctx),
|
||||
from_email=f'"Arch Linux: Recent news updates: {newsitem.author.get_full_name()}" <{settings.ANNOUNCE_EMAIL}>',
|
||||
from_email=from_,
|
||||
to=[settings.ANNOUNCE_EMAIL],
|
||||
headers=headers).send()
|
||||
return super(NewsCreateView, self).form_valid(form)
|
||||
|
@@ -5,7 +5,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "World-Gremlins",
|
||||
"name": "world-gremlins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": true
|
||||
@@ -17,7 +17,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "Galaxy-Gremlins",
|
||||
"name": "galaxy-gremlins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": true
|
||||
@@ -29,7 +29,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "System",
|
||||
"name": "system",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
@@ -41,7 +41,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "World",
|
||||
"name": "world",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
@@ -53,7 +53,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "Galaxy",
|
||||
"name": "galaxy",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
@@ -65,7 +65,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "Lib32",
|
||||
"name": "lib32",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
@@ -77,7 +77,7 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "Lib32-Gremlins",
|
||||
"name": "lib32-gremlins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": true
|
||||
@@ -89,10 +89,58 @@
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": false,
|
||||
"name": "System-Gremlins",
|
||||
"name": "system-gremlins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 9,
|
||||
"model": "main.repo",
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": true,
|
||||
"name": "system-goblins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 10,
|
||||
"model": "main.repo",
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": true,
|
||||
"name": "world-goblins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 11,
|
||||
"model": "main.repo",
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": true,
|
||||
"name": "galaxy-goblins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 12,
|
||||
"model": "main.repo",
|
||||
"fields": {
|
||||
"bugs_category": 0,
|
||||
"staging": true,
|
||||
"name": "lib32-goblins",
|
||||
"bugs_project": 0,
|
||||
"svn_root": "packages",
|
||||
"testing": false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -52,8 +52,9 @@ def create_specification(package, log, finder):
|
||||
return spec
|
||||
|
||||
|
||||
def get_last_log(repo, pkgbase):
|
||||
# Gitlab requires the path to the gitlab repo to be html encoded and project name encoded in a different special way
|
||||
def get_tag_info(repo, pkgbase, version):
|
||||
# Gitlab requires the path to the gitlab repo to be html encoded and
|
||||
# project name encoded in a different special way
|
||||
pkgrepo = urllib.parse.quote_plus(f'{settings.GITLAB_PACKAGE_REPO}/') + gitlab_project_name_to_path(pkgbase)
|
||||
url = f'https://{settings.GITLAB_INSTANCE}/api/v4/projects/{pkgrepo}/repository/tags'
|
||||
|
||||
@@ -65,8 +66,12 @@ def get_last_log(repo, pkgbase):
|
||||
return None
|
||||
|
||||
tags = r.json()
|
||||
|
||||
# filter out unrelated tags
|
||||
tags = [tag for tag in tags if tag["name"] == version]
|
||||
|
||||
if len(tags) == 0:
|
||||
logger.error("No tags found for pkgbase %s (%s)", pkgbase, repo)
|
||||
logger.error("No tags found for pkgbase %s (%s) version %s", pkgbase, repo, version)
|
||||
return None
|
||||
|
||||
tag = tags[0]
|
||||
@@ -89,7 +94,7 @@ def add_signoff_comments():
|
||||
if not group.default_spec:
|
||||
continue
|
||||
|
||||
log = get_last_log(group.repo, group.pkgbase)
|
||||
log = get_tag_info(group.repo, group.pkgbase, group.version)
|
||||
if log is None:
|
||||
continue
|
||||
|
||||
@@ -108,7 +113,8 @@ def cleanup_signoff_comments():
|
||||
id_signoffs = [signoff.id for g in groups for signoff in g.signoffs]
|
||||
logger.info("Keeping %s signoffs", len(id_signoffs))
|
||||
# FakeSignoffSpecification's have no id
|
||||
id_signoffspecs = [g.specification.id for g in groups if not isinstance(g.specification, FakeSignoffSpecification)]
|
||||
id_signoffspecs = [g.specification.id for g in groups if not isinstance(g.specification,
|
||||
FakeSignoffSpecification)]
|
||||
logger.info("Keeping %s signoffspecifications", len(id_signoffspecs))
|
||||
|
||||
Signoff.objects.exclude(id__in=id_signoffs).delete()
|
||||
|
@@ -253,7 +253,8 @@ class UpdateManager(models.Manager):
|
||||
if new_pkg:
|
||||
update.action_flag = CHANGE
|
||||
# ensure we should even be logging this
|
||||
if old_pkg.pkgver == new_pkg.pkgver and old_pkg.pkgrel == new_pkg.pkgrel and old_pkg.epoch == new_pkg.epoch:
|
||||
if old_pkg.pkgver == new_pkg.pkgver and old_pkg.pkgrel == new_pkg.pkgrel \
|
||||
and old_pkg.epoch == new_pkg.epoch:
|
||||
# all relevant fields were the same; e.g. a force update
|
||||
return
|
||||
else:
|
||||
@@ -395,7 +396,8 @@ class RelatedToBase(models.Model):
|
||||
# actually satisfy the requirements
|
||||
if self.comparison and self.version:
|
||||
alpm = AlpmAPI()
|
||||
pkgs = [pkg for pkg in pkgs if not alpm.available or alpm.compare_versions(pkg.full_version, self.comparison, self.version)]
|
||||
pkgs = [pkg for pkg in pkgs if not alpm.available or alpm.compare_versions(pkg.full_version,
|
||||
self.comparison, self.version)]
|
||||
if len(pkgs) == 0:
|
||||
# couldn't find a package in the DB
|
||||
# it should be a virtual depend (or a removed package)
|
||||
|
@@ -26,9 +26,9 @@ class RematchDeveloperTest(TransactionTestCase):
|
||||
self.package.delete()
|
||||
|
||||
def test_basic(self):
|
||||
with mock.patch('packages.management.commands.populate_signoffs.get_last_log') as get_last_log:
|
||||
with mock.patch('packages.management.commands.populate_signoffs.get_tag_info') as get_tag_info:
|
||||
comment = 'upgpkg: 0.1-1: rebuild'
|
||||
get_last_log.return_value = {'message': f'{comment}\n', 'author': 'foo@archlinux.org'}
|
||||
get_tag_info.return_value = {'message': f'{comment}\n', 'author': 'foo@archlinux.org'}
|
||||
call_command('populate_signoffs')
|
||||
|
||||
signoff_spec = SignoffSpecification.objects.first()
|
||||
@@ -36,8 +36,8 @@ class RematchDeveloperTest(TransactionTestCase):
|
||||
assert signoff_spec.pkgbase == self.package.pkgbase
|
||||
|
||||
def test_invalid(self):
|
||||
with mock.patch('packages.management.commands.populate_signoffs.get_last_log') as get_last_log:
|
||||
get_last_log.return_value = None
|
||||
with mock.patch('packages.management.commands.populate_signoffs.get_tag_info') as get_tag_info:
|
||||
get_tag_info.return_value = None
|
||||
call_command('populate_signoffs')
|
||||
|
||||
assert SignoffSpecification.objects.count() == 0
|
||||
|
@@ -67,6 +67,7 @@ def test_sort(client, package):
|
||||
def test_packages(client, package):
|
||||
response = client.get('/opensearch/packages/')
|
||||
assert response.status_code == 200
|
||||
assert 'template="example.com/opensearch/packages/"' in response.content.decode()
|
||||
|
||||
|
||||
def test_packages_suggest(client, package):
|
||||
|
@@ -5,6 +5,7 @@ from collections import defaultdict
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
@@ -21,10 +22,10 @@ from ..utils import get_wrong_permissions, multilib_differences
|
||||
@require_safe
|
||||
@cache_control(public=True, max_age=86400)
|
||||
def opensearch(request):
|
||||
domain = "%s://%s" % ('https', request.META.get('HTTP_HOST'))
|
||||
current_site = Site.objects.get_current()
|
||||
|
||||
return render(request, 'packages/opensearch.xml',
|
||||
{'domain': domain},
|
||||
{'domain': current_site.domain},
|
||||
content_type='application/opensearchdescription+xml')
|
||||
|
||||
|
||||
@@ -140,8 +141,14 @@ def sonames(request):
|
||||
name = request.GET.get('name')
|
||||
|
||||
if name:
|
||||
sonames = Soname.objects.filter(name__startswith=name).values('pkg__pkgname', 'pkg__pkgver', 'pkg__pkgrel', 'pkg__epoch', 'pkg__repo__name')
|
||||
packages = [{'pkgname': soname['pkg__pkgname'], 'pkgrel': soname['pkg__pkgrel'], 'pkgver': soname['pkg__pkgver'], 'epoch': soname['pkg__epoch'], 'repo': soname['pkg__repo__name'].lower()} for soname in sonames]
|
||||
sonames = Soname.objects.filter(name__startswith=name).values('pkg__pkgname',
|
||||
'pkg__pkgver',
|
||||
'pkg__pkgrel',
|
||||
'pkg__epoch',
|
||||
'pkg__repo__name')
|
||||
packages = [{'pkgname': soname['pkg__pkgname'], 'pkgrel': soname['pkg__pkgrel'],
|
||||
'pkgver': soname['pkg__pkgver'], 'epoch': soname['pkg__epoch'],
|
||||
'repo': soname['pkg__repo__name'].lower()} for soname in sonames]
|
||||
else:
|
||||
return HttpResponseBadRequest('name parameter is required')
|
||||
|
||||
|
@@ -38,7 +38,8 @@ class FlagForm(forms.Form):
|
||||
# make sure the message isn't garbage (only punctuation or whitespace)
|
||||
# or spam (using a simple denylist)
|
||||
# and ensure a certain minimum length
|
||||
if re.match(r'^[^0-9A-Za-z]+$', data) or any(fd.keyword in data for fd in FlagDenylist.objects.all()) or len(data) < 3:
|
||||
if re.match(r'^[^0-9A-Za-z]+$', data) or any(fd.keyword in data for fd in FlagDenylist.objects.all()) \
|
||||
or len(data) < 3:
|
||||
raise forms.ValidationError("Enter a valid and useful out-of-date message.")
|
||||
return data
|
||||
|
||||
|
@@ -50,7 +50,8 @@ class Migration(migrations.Migration):
|
||||
('author', models.CharField(max_length=255)),
|
||||
('publishdate', models.DateTimeField(db_index=True, verbose_name='publish date')),
|
||||
('url', models.CharField(max_length=255, verbose_name='URL')),
|
||||
('feed', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='feed', to='planet.Feed')),
|
||||
('feed', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='feed', to='planet.Feed')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'Feed Items',
|
||||
|
@@ -14,6 +14,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='feeditem',
|
||||
name='feed',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='items', to='planet.feed'),
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='items', to='planet.feed'),
|
||||
),
|
||||
]
|
||||
|
@@ -8,7 +8,7 @@ fi
|
||||
|
||||
printf "populatepackages.sh\nretrieving package files from %s\n" "$path"
|
||||
|
||||
repos="system world galaxy lib32 system-gremlins world-gremlins galaxy-gremlins lib32-gremlins"
|
||||
repos="system world galaxy lib32 system-gremlins world-gremlins galaxy-gremlins lib32-gremlins system-goblins world-goblins galaxy-goblins lib32-goblins"
|
||||
|
||||
for repo in $repos
|
||||
do
|
||||
|
@@ -3,6 +3,7 @@ from datetime import datetime
|
||||
from operator import attrgetter
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db.models import Count, Q
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
@@ -25,12 +26,12 @@ def index(request):
|
||||
else:
|
||||
def updates():
|
||||
return get_recent_updates()
|
||||
domain = "%s://%s" % (request.scheme, request.META.get('HTTP_HOST'))
|
||||
current_site = Site.objects.get_current()
|
||||
context = {
|
||||
'news_updates': News.objects.order_by('-postdate', '-id')[:15],
|
||||
'pkg_updates': updates,
|
||||
'staff_groups': StaffGroup.objects.all(),
|
||||
'domain': domain,
|
||||
'domain': current_site.domain,
|
||||
}
|
||||
return render(request, 'public/index.html', context)
|
||||
|
||||
@@ -92,8 +93,9 @@ def feeds(request):
|
||||
@cache_control(max_age=307)
|
||||
def keys(request):
|
||||
profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id')
|
||||
users = User.objects.filter(
|
||||
is_active=True, userprofile__id__in=profile_ids).order_by('first_name', 'last_name').select_related('userprofile')
|
||||
users = User.objects.filter(is_active=True,
|
||||
userprofile__id__in=profile_ids).order_by('first_name',
|
||||
'last_name').select_related('userprofile')
|
||||
user_key_ids = frozenset(user.userprofile.pgp_key[-16:] for user in users
|
||||
if user.userprofile.pgp_key)
|
||||
|
||||
|
@@ -9,8 +9,10 @@ from .views import ReleaseDetailView, ReleaseListView
|
||||
releases_patterns = [
|
||||
path('', ReleaseListView.as_view(), name='releng-release-list'),
|
||||
path('json/', views.releases_json, name='releng-release-list-json'),
|
||||
re_path(r'^(?P<version>[-.\w]+)/$', cache_page(311)(ReleaseDetailView.as_view()), name='releng-release-detail'),
|
||||
re_path(r'^(?P<version>[-.\w]+)/torrent/$', cache_page(311)(views.release_torrent), name='releng-release-torrent'),
|
||||
re_path(r'^(?P<version>[-.\w]+)/$', cache_page(311)(ReleaseDetailView.as_view()),
|
||||
name='releng-release-detail'),
|
||||
re_path(r'^(?P<version>[-.\w]+)/torrent/$', cache_page(311)(views.release_torrent),
|
||||
name='releng-release-torrent'),
|
||||
]
|
||||
|
||||
netboot_patterns = [
|
||||
|
@@ -1,5 +1,5 @@
|
||||
-e git+https://github.com/fredj/cssmin.git@master#egg=cssmin
|
||||
Django==5.0.8
|
||||
Django==5.0.11
|
||||
IPy==1.1
|
||||
Markdown==3.3.7
|
||||
bencode.py==4.0.0
|
||||
@@ -7,14 +7,14 @@ django-countries==7.6.1
|
||||
django-extensions==3.2.3
|
||||
jsmin==3.0.1
|
||||
pgpdump==1.5
|
||||
parse==1.19.0
|
||||
parse==1.20.2
|
||||
sqlparse==0.5.0
|
||||
django-csp==3.7
|
||||
django-csp==3.8
|
||||
ptpython==2.0.4
|
||||
feedparser==6.0.10
|
||||
feedparser==6.0.11
|
||||
bleach==6.0.0
|
||||
requests==2.32.0
|
||||
xtarfile==0.1.0
|
||||
zstandard==0.17.0
|
||||
whitenoise==6.7.0
|
||||
requests==2.32.3
|
||||
xtarfile==0.2.1
|
||||
zstandard==0.23.0
|
||||
whitenoise==6.8.2
|
||||
django-prometheus==2.3.1
|
||||
|
@@ -24,7 +24,6 @@ select = [
|
||||
]
|
||||
|
||||
ignore = [
|
||||
"E501", # line lengt violation
|
||||
"E731", # Do not assign a `lambda` expression, use a `def`
|
||||
"B904", # Within an `except` clause, raise exceptions with `raise ... from err`
|
||||
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
|
||||
@@ -34,3 +33,8 @@ ignore = [
|
||||
"DJ008", # Model does not define `__str__` method
|
||||
"DJ012", # Order of model's inner classes, methods, and fields does not follow the Django Style Guide: `Meta` class should come before `get_absolute_url`
|
||||
]
|
||||
|
||||
exclude = [
|
||||
"*/migrations/*.py", # Ignore Django migrations
|
||||
"src/cssmin/*" # cssmin, not our code
|
||||
]
|
||||
|
@@ -41,9 +41,6 @@ SITE_ID = 1
|
||||
DATE_FORMAT = 'Y-m-d'
|
||||
DATETIME_FORMAT = 'Y-m-d H:i'
|
||||
|
||||
# Disable so our own DATE_FORMAT/DATETIME_FORMAT is used.
|
||||
USE_L10N = False
|
||||
|
||||
# Login URL configuration
|
||||
LOGIN_URL = '/login/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
@@ -270,7 +267,9 @@ if DEBUG_TOOLBAR:
|
||||
INSTALLED_APPS = [*list(INSTALLED_APPS), 'debug_toolbar']
|
||||
|
||||
if PROMETHEUS_METRICS:
|
||||
MIDDLEWARE = ['django_prometheus.middleware.PrometheusBeforeMiddleware', *list(MIDDLEWARE), 'django_prometheus.middleware.PrometheusAfterMiddleware']
|
||||
MIDDLEWARE = ['django_prometheus.middleware.PrometheusBeforeMiddleware',
|
||||
*list(MIDDLEWARE),
|
||||
'django_prometheus.middleware.PrometheusAfterMiddleware']
|
||||
|
||||
INSTALLED_APPS = [*list(INSTALLED_APPS), 'django_prometheus']
|
||||
|
||||
|
@@ -754,6 +754,10 @@ table.results {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.results [hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* pkglist: layout */
|
||||
#pkglist-about {
|
||||
margin-top: 1.5em;
|
||||
@@ -1056,12 +1060,12 @@ table td.country {
|
||||
background: #ffd;
|
||||
}
|
||||
|
||||
.results tr:nth-child(even),
|
||||
.results tr:nth-child(even of :not([hidden])),
|
||||
#article-list tr:nth-child(even) {
|
||||
background: #e4eeff;
|
||||
}
|
||||
|
||||
.results tr:nth-child(odd),
|
||||
.results tr:nth-child(odd of :not([hidden])),
|
||||
#article-list tr:nth-child(odd) {
|
||||
background: #fff;
|
||||
}
|
||||
|
@@ -212,8 +212,14 @@ function filter_pkgs_list(filter_ele, tbody_ele) {
|
||||
rows = rows.has('.incomplete');
|
||||
}
|
||||
/* hide all rows, then show the set we care about */
|
||||
all_rows.hide();
|
||||
rows.show();
|
||||
// note that we don't use .hide() from jQuery because it adds display:none
|
||||
// which is very expensive to query in CSS ([style*="display: none"])
|
||||
all_rows.each(function() {
|
||||
$(this).attr('hidden', true);
|
||||
});
|
||||
rows.each(function() {
|
||||
$(this).removeAttr('hidden');
|
||||
});
|
||||
$('#filter-count').text(rows.length);
|
||||
/* make sure we update the odd/even styling from sorting */
|
||||
$('.results').trigger('applyWidgets', [false]);
|
||||
@@ -330,8 +336,14 @@ function filter_signoffs() {
|
||||
rows = rows.has('td.signoff-no');
|
||||
}
|
||||
/* hide all rows, then show the set we care about */
|
||||
all_rows.hide();
|
||||
rows.show();
|
||||
// note that we don't use .hide() from jQuery because it adds display:none
|
||||
// which is very expensive to query in CSS ([style*="display: none"])
|
||||
all_rows.each(function() {
|
||||
$(this).attr('hidden', true);
|
||||
});
|
||||
rows.each(function() {
|
||||
$(this).removeAttr('hidden');
|
||||
});
|
||||
$('#filter-count').text(rows.length);
|
||||
/* make sure we update the odd/even styling from sorting */
|
||||
$('.results').trigger('applyWidgets', [false]);
|
||||
|
@@ -30,7 +30,7 @@
|
||||
<tbody>
|
||||
{% for entry in admin_log %}
|
||||
<tr>
|
||||
<th scope="row">{{ entry.action_time|date:"DATETIME_FORMAT" }}</th>
|
||||
<th scope="row">{{ entry.action_time|date:"Y-m-d H:i" }}</th>
|
||||
{% if log_user %}
|
||||
<td>{{ entry.user.username }}{% if entry.user.get_full_name %} ({{ entry.user.get_full_name }}){% endif %}</td>
|
||||
{% else %}
|
||||
|
@@ -36,8 +36,8 @@
|
||||
{% endif %}{% endwith %}</td>
|
||||
<td>{{ pkg.repo.name }}</td>
|
||||
<td>{{ pkg.arch.name }}</td>
|
||||
<td>{{ pkg.flag_date|date }}</td>
|
||||
<td>{{ pkg.last_update|date }}</td>
|
||||
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg.last_update|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr class="empty"><td colspan="7"><em>No flagged packages to display</em></td></tr>
|
||||
@@ -68,7 +68,7 @@
|
||||
<td>{{ group.version }}</td>
|
||||
<td>{{ group.arch.name }}</td>
|
||||
<td>{{ group.target_repo }}</td>
|
||||
<td>{{ group.last_update|date }}</td>
|
||||
<td>{{ group.last_update|date:"Y-m-d" }}</td>
|
||||
{% if group.specification.known_bad %}
|
||||
<td class="approval signoff-bad">Bad</td>
|
||||
{% else %}
|
||||
@@ -138,7 +138,7 @@
|
||||
<tr>
|
||||
<td class="wrap"><a href="{{ todo.get_absolute_url }}"
|
||||
title="View todo list: {{ todo.name }}">{{ todo.name }}</a></td>
|
||||
<td>{{ todo.created|date }}</td>
|
||||
<td>{{ todo.created|date:"Y-m-d" }}</td>
|
||||
<td>{{ todo.creator.get_full_name }}</td>
|
||||
<td>{{ todo.pkg_count }}</td>
|
||||
<td>{{ todo.incomplete_count }}</td>
|
||||
|
@@ -60,9 +60,9 @@
|
||||
{% else %}
|
||||
<td>{{ pkg.full_version }}</td>
|
||||
{% endif %}
|
||||
<td>{{ pkg.last_update|date }}</td>
|
||||
<td>{{ pkg.build_date|date }}</td>
|
||||
<td>{{ pkg.flag_date|date }}</td>
|
||||
<td>{{ pkg.last_update|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg.build_date|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td>
|
||||
{% for attr in column_attrs %}
|
||||
<td>{{ pkg|attribute:attr }}</td>
|
||||
{% endfor %}
|
||||
|
@@ -33,7 +33,7 @@
|
||||
<tbody>
|
||||
{% for item in news_list %}
|
||||
<tr>
|
||||
<td>{{ item.postdate|date }}</td>
|
||||
<td>{{ item.postdate|date:"Y-m-d" }}</td>
|
||||
<td class="wrap"><a href="{{ item.get_absolute_url }}"
|
||||
title="View: {{ item.title }}">{{ item.title }}</a></td>
|
||||
<td>{{ item.author.get_full_name }}</td>
|
||||
|
@@ -25,7 +25,7 @@
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<p class="article-info">{{ news.postdate|date }} - {{ news.author.get_full_name }}</p>
|
||||
<p class="article-info">{{ news.postdate|date:"Y-m-d" }} - {{ news.author.get_full_name }}</p>
|
||||
|
||||
<div class="article-content" itemprop="articleBody">{{ news.html }}</div>
|
||||
</div>
|
||||
|
@@ -29,8 +29,8 @@
|
||||
<td><span{% if pkg2.flag_date %} class="flagged"{% endif %}>{{ pkg2.full_version }}</span></td>
|
||||
<td>{% pkg_details_link pkg2 %}</td>
|
||||
<td>{{ pkg2.repo }}</td>
|
||||
<td>{{ pkg1.last_update|date }}</td>
|
||||
<td>{{ pkg2.last_update|date }}</td>
|
||||
<td>{{ pkg1.last_update|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg2.last_update|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
{% load package_extras %}
|
||||
{% load humanize %}
|
||||
{% load details_link %}
|
||||
|
||||
{% block title %}Arch Linux - Flag Package - {{ package.pkgname }} {{ package.full_version }} ({{ package.arch.name }}){% endblock %}
|
||||
{% block head %}<meta name="robots" content="noindex"/>{% endblock %}
|
||||
@@ -29,9 +30,9 @@
|
||||
with your additional text.</p>
|
||||
|
||||
<p><strong>Note:</strong> Do <em>not</em> use this facility if the
|
||||
package is broken! The package will be unflagged and the report will be ignored!
|
||||
<a href="https://bugs.archlinux.org/" title="Arch Linux Bugtracker">Use the
|
||||
bugtracker to file a bug</a> instead.</p>
|
||||
package is broken! The package will be unflagged and the report will be ignored! File an issue on
|
||||
<a href="{% bugs_list package %}" title="Bug tickets for {{ package }}">the package's GitLab repository</a>
|
||||
instead.</p>
|
||||
|
||||
<p>Please confirm your flag request for {{package.pkgname}}:</p>
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<td><a href="/groups/{{ grp.arch }}/{{ grp.name }}/"
|
||||
title="Group details for {{ grp.name }}">{{ grp.name }}</a></td>
|
||||
<td>{{ grp.count }}</td>
|
||||
<td>{{ grp.last_update|date }}</td>
|
||||
<td>{{ grp.last_update|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@@ -30,7 +30,7 @@
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pkg.flag_date %}
|
||||
<li><span class="flagged">Flagged out-of-date on {{ pkg.flag_date|date }}</span></li>
|
||||
<li><span class="flagged">Flagged out-of-date on {{ pkg.flag_date|date:"Y-m-d" }}</span></li>
|
||||
{% with tp=pkg.in_testing %}{% if tp %}
|
||||
<li><span class="flagged">Version
|
||||
<a href="{{ tp.get_absolute_url }}"
|
||||
@@ -98,8 +98,8 @@
|
||||
title="Browse packages for {{ pkg.arch.name }} architecture">{{ pkg.arch.name }}</a></td>
|
||||
</tr><tr>
|
||||
<th>Repository:</th>
|
||||
<td><a href="/packages/?repo={{ pkg.repo.name|capfirst }}"
|
||||
title="Browse the {{ pkg.repo.name|capfirst }} repository">{{ pkg.repo.name|capfirst }}</a></td>
|
||||
<td><a href="/packages/?repo={{ pkg.repo.name }}"
|
||||
title="Browse the {{ pkg.repo.name }} repository">{{ pkg.repo.name }}</a></td>
|
||||
</tr>
|
||||
{% if pkg.pkgname == pkg.pkgbase %}
|
||||
{% with splits=pkg.split_packages %}{% if splits %}
|
||||
@@ -188,19 +188,19 @@
|
||||
{% else %}{{ pkg.packager_str }}{% endif %}{% endwith %}</td>
|
||||
</tr><tr>
|
||||
<th>Build Date:</th>
|
||||
<td>{{ pkg.build_date|date:"DATETIME_FORMAT" }} UTC</td>
|
||||
<td>{{ pkg.build_date|date:"Y-m-d H:i" }} UTC</td>
|
||||
</tr>{% if pkg.signature %}<tr>
|
||||
<th>Signed By:</th>
|
||||
<td>{% with signer=pkg.signer %}{% if signer %}{% pgp_key_link pkg.signature.key_id signer.get_full_name|safe %}{% else %}Unknown ({% pgp_key_link pkg.signature.key_id|safe %}){% endif %}{% endwith %}</td>
|
||||
</tr><tr>
|
||||
<th>Signature Date:</th>
|
||||
<td>{{ pkg.signature.creation_time|date:"DATETIME_FORMAT" }} UTC</td>
|
||||
<td>{{ pkg.signature.creation_time|date:"Y-m-d H:i" }} UTC</td>
|
||||
</tr>{% else %}<tr>
|
||||
<th>Signed By:</th>
|
||||
<td>Unsigned</td>
|
||||
</tr>{% endif %}<tr>
|
||||
<th>Last Updated:</th>
|
||||
<td>{{ pkg.last_update|date:"DATETIME_FORMAT" }} UTC{% if pkg.is_recent %} <span class="recent" title="Your mirror may not yet have this package version">({{ pkg.last_update|naturaltime }})</span>{% endif %}</td>
|
||||
<td>{{ pkg.last_update|date:"Y-m-d H:i" }} UTC{% if pkg.is_recent %} <span class="recent" title="Your mirror may not yet have this package version">({{ pkg.last_update|naturaltime }})</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% if user.is_authenticated %}<tr>
|
||||
<th>Reproducible Status:</th>
|
||||
@@ -213,7 +213,7 @@
|
||||
{% endif %}
|
||||
{% if user.is_authenticated %}{% with flag_request=pkg.flag_request %}{% if flag_request %}<tr>
|
||||
<th>Last Flag Request:</th>
|
||||
<td class="wrap">From {{ flag_request.who }} on {{ flag_request.created|date }}:<br/>
|
||||
<td class="wrap">From {{ flag_request.who }} on {{ flag_request.created|date:"Y-m-d" }}:<br/>
|
||||
<div class="userdata">{{ flag_request.message|linebreaksbr|default:"{no message}" }}</div></td>
|
||||
</tr>{% endif %}{% endwith %}{% endif %}
|
||||
</table>
|
||||
|
@@ -33,8 +33,8 @@
|
||||
<td>{{ pkg.full_version }}</td>
|
||||
{% endif %}
|
||||
<td class="wrap">{{ pkg.pkgdesc }}</td>
|
||||
<td>{{ pkg.last_update|date }}</td>
|
||||
<td>{{ pkg.flag_date|date }}</td>
|
||||
<td>{{ pkg.last_update|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@@ -62,7 +62,7 @@
|
||||
{% for pkg in exact_matches %}
|
||||
<tr>
|
||||
<td>{{ pkg.arch.name }}</td>
|
||||
<td>{{ pkg.repo.name|capfirst }}</td>
|
||||
<td>{{ pkg.repo.name }}</td>
|
||||
<td>{% pkg_details_link pkg %}</td>
|
||||
{% if pkg.flag_date %}
|
||||
<td><span class="flagged" title="Flagged out-of-date">{{ pkg.full_version }}</span></td>
|
||||
@@ -70,8 +70,8 @@
|
||||
<td>{{ pkg.full_version }}</td>
|
||||
{% endif %}
|
||||
<td class="wrap">{{ pkg.pkgdesc }}</td>
|
||||
<td>{{ pkg.last_update|date }}</td>
|
||||
<td>{{ pkg.flag_date|date }}</td>
|
||||
<td>{{ pkg.last_update|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -109,7 +109,7 @@
|
||||
<td><input type="checkbox" name="pkgid" value="{{ pkg.id }}" /></td>
|
||||
{% endif %}
|
||||
<td>{{ pkg.arch.name }}</td>
|
||||
<td>{{ pkg.repo.name|capfirst }}</td>
|
||||
<td>{{ pkg.repo.name }}</td>
|
||||
<td>{% pkg_details_link pkg %}</td>
|
||||
{% if pkg.flag_date %}
|
||||
<td><span class="flagged" title="Flagged out-of-date">{{ pkg.full_version }}</span></td>
|
||||
@@ -117,8 +117,8 @@
|
||||
<td>{{ pkg.full_version }}</td>
|
||||
{% endif %}
|
||||
<td class="wrap">{{ pkg.pkgdesc }}</td>
|
||||
<td>{{ pkg.last_update|date }}</td>
|
||||
<td>{{ pkg.flag_date|date }}</td>
|
||||
<td>{{ pkg.last_update|date:"Y-m-d" }}</td>
|
||||
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr class="empty"><td colspan="{% if perms.main.change_package %}8{% else %}7{% endif %}"><em>No matching packages found</em></td></tr>
|
||||
|
@@ -56,7 +56,7 @@
|
||||
<td>{{ group.target_repo }}</td>
|
||||
<td>{{ group.packager|default:"Unknown" }}</td>
|
||||
<td>{{ group.packages|length }}</td>
|
||||
<td class="epoch-{{ group.last_update|date:'U' }}">{{ group.last_update|date }}</td>
|
||||
<td class="epoch-{{ group.last_update|date:'U' }}">{{ group.last_update|date:"Y-m-d" }}</td>
|
||||
{% if group.specification.known_bad %}
|
||||
<td class="approval signoff-bad">Bad</td>
|
||||
{% else %}
|
||||
|
@@ -24,7 +24,7 @@
|
||||
<a href="{{ entry.url }}"
|
||||
title="View full article: {{ entry.title }}">{{ entry.title }}</a>
|
||||
</h4>
|
||||
<p class="timestamp">{{ entry.publishdate|date }}</p>
|
||||
<p class="timestamp">{{ entry.publishdate|date:"Y-m-d" }}</p>
|
||||
<div class="article-content">
|
||||
{{ entry.summary |safe }}
|
||||
</div>
|
||||
|
@@ -50,7 +50,7 @@
|
||||
<a href="{{ news.get_absolute_url }}"
|
||||
title="View full article: {{ news.title }}">{{ news.title }}</a>
|
||||
</h4>
|
||||
<p class="timestamp">{{ news.postdate|date }}</p>
|
||||
<p class="timestamp">{{ news.postdate|date:"Y-m-d" }}</p>
|
||||
<div class="article-content">
|
||||
{% if forloop.counter0 == 0 %}{{ news.html|truncatewords_html:300 }}
|
||||
{% else %}{{ news.html|truncatewords_html:100 }}{% endif %}
|
||||
@@ -63,7 +63,7 @@
|
||||
</h3>
|
||||
<dl class="newslist">
|
||||
{% endif %}
|
||||
<dt>{{ news.postdate|date }}</dt>
|
||||
<dt>{{ news.postdate|date:"Y-m-d" }}</dt>
|
||||
<dd>
|
||||
<a href="{{ news.get_absolute_url }}"
|
||||
title="View full article: {{ news.title }}">{{ news.title }}</a>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<h2>{{ release.version }}</h2>
|
||||
|
||||
<ul>
|
||||
<li><strong>Release Date:</strong> {{ release.release_date|date }}</li>
|
||||
<li><strong>Release Date:</strong> {{ release.release_date|date:"Y-m-d" }}</li>
|
||||
{% if release.kernel_version %}<li><strong>Kernel Version:</strong> {{ release.kernel_version }}</li>{% endif %}
|
||||
<li><strong>Available:</strong> {{ release.available|yesno|capfirst }}</li>
|
||||
{% if release.torrent_data %}
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
<ul>
|
||||
<li><strong>Comment:</strong> {{ torrent.comment }}</li>
|
||||
<li><strong>Creation Date:</strong> {{ torrent.creation_date|date:"DATETIME_FORMAT" }} UTC</li>
|
||||
<li><strong>Creation Date:</strong> {{ torrent.creation_date|date:"Y-m-d H:i" }} UTC</li>
|
||||
<li><strong>Created By:</strong> {{ torrent.created_by }}</li>
|
||||
<li><strong>Announce URL:</strong> {{ torrent.announce }}</li>
|
||||
<li><strong>File Name:</strong> {{ torrent.file_name }}</li>
|
||||
|
@@ -42,7 +42,7 @@
|
||||
<a href="{{ item.magnet_uri }}"
|
||||
title="Get magnet link for {{ item.version }}"><img width="12" height="12" src="{% static "magnet.png" %}" alt="Magnet"/></a>
|
||||
{% endif %}</td>
|
||||
<td>{{ item.release_date|date }}</td>
|
||||
<td>{{ item.release_date|date:"Y-m-d" }}</td>
|
||||
<td><a href="{{ item.get_absolute_url }}" title="Release details for {{ item.version }}">{{ item.version }}</a></td>
|
||||
<td>{{ item.kernel_version|default:"" }}</td>
|
||||
<td class="available-{{ item.available|yesno }}">{{ item.available|yesno|capfirst }}</td>
|
||||
|
@@ -37,7 +37,7 @@
|
||||
<tr>
|
||||
<td class="wrap"><a href="{{ list.get_absolute_url }}"
|
||||
title="View todo list: {{ list.name }}">{{ list.name }}</a></td>
|
||||
<td>{{ list.created|date }}</td>
|
||||
<td>{{ list.created|date:"Y-m-d" }}</td>
|
||||
<td>{{ list.creator.get_full_name }}</td>
|
||||
<td>{{ list.pkg_count }}</td>
|
||||
<td>{{ list.incomplete_count }}</td>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div class="todo-info">{{ list.created|date }} - {{ list.creator.get_full_name }}</div>
|
||||
<div class="todo-info">{{ list.created|date:"Y-m-d" }} - {{ list.creator.get_full_name }}</div>
|
||||
|
||||
<div class="todo-description">
|
||||
{{list.stripped_description|default:'(no description)'|urlize|linebreaks}}
|
||||
|
@@ -28,7 +28,9 @@ class Migration(migrations.Migration):
|
||||
('created', models.DateTimeField(db_index=True)),
|
||||
('last_modified', models.DateTimeField(editable=False)),
|
||||
('raw', models.TextField(blank=True)),
|
||||
('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='created_todolists', to=settings.AUTH_USER_MODEL)),
|
||||
('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name='created_todolists',
|
||||
to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'get_latest_by': 'created',
|
||||
@@ -43,13 +45,16 @@ class Migration(migrations.Migration):
|
||||
('created', models.DateTimeField(editable=False)),
|
||||
('last_modified', models.DateTimeField(editable=False)),
|
||||
('removed', models.DateTimeField(blank=True, null=True)),
|
||||
('status', models.SmallIntegerField(choices=[(0, 'Incomplete'), (1, 'Complete'), (2, 'In-progress')], default=0)),
|
||||
('status', models.SmallIntegerField(choices=[(0, 'Incomplete'), (1, 'Complete'), (2, 'In-progress')],
|
||||
default=0)),
|
||||
('comments', models.TextField(blank=True, null=True)),
|
||||
('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Arch')),
|
||||
('pkg', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.Package')),
|
||||
('pkg', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL,
|
||||
to='main.Package')),
|
||||
('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Repo')),
|
||||
('todolist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='todolists.Todolist')),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL,
|
||||
to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'get_latest_by': 'created',
|
||||
|
@@ -13,6 +13,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='todolist',
|
||||
name='kind',
|
||||
field=models.SmallIntegerField(choices=[(0, 'Rebuild'), (1, 'Task')], default=0, help_text='(Rebuild for soname bumps, Task for independent tasks)'),
|
||||
field=models.SmallIntegerField(choices=[(0, 'Rebuild'), (1, 'Task')], default=0,
|
||||
help_text='(Rebuild for soname bumps, Task for independent tasks)'),
|
||||
),
|
||||
]
|
||||
|
@@ -23,7 +23,8 @@ class Todolist(models.Model):
|
||||
description = models.TextField()
|
||||
creator = models.ForeignKey(User, on_delete=models.PROTECT, related_name="created_todolists")
|
||||
created = models.DateTimeField(db_index=True)
|
||||
kind = models.SmallIntegerField(default=REBUILD, choices=KIND_CHOICES, help_text='(Rebuild for soname bumps, Task for independent tasks)')
|
||||
kind = models.SmallIntegerField(default=REBUILD, choices=KIND_CHOICES,
|
||||
help_text='(Rebuild for soname bumps, Task for independent tasks)')
|
||||
last_modified = models.DateTimeField(editable=False)
|
||||
raw = models.TextField(blank=True)
|
||||
|
||||
|
Reference in New Issue
Block a user