31 Commits

Author SHA1 Message Date
305cbdc3d8 different take on the dark theme media query
All checks were successful
Github-Actions / build (push) Successful in 47s
Docker Image CI / build (push) Successful in 4m34s
2024-08-08 19:14:06 -05:00
9a05c787d7 feature: use light colors if light color scheme is preferred
All checks were successful
Github-Actions / build (push) Successful in 47s
Docker Image CI / build (push) Successful in 4m34s
This one's for you, nottherealstevie!
2024-08-08 13:08:45 -05:00
46f4123e45 Update distro name in opensearch.xml 2024-08-08 12:29:04 -05:00
498f565866 Merge upstream changes
All checks were successful
Github-Actions / build (push) Successful in 47s
Docker Image CI / build (push) Successful in 4m38s
2024-08-08 09:29:45 -05:00
60ef0b9766 fix mangled hardcoded protocol 2024-08-08 09:28:36 -05:00
e83a93055a update actions
All checks were successful
Github-Actions / build (push) Successful in 52s
Docker Image CI / build (push) Successful in 3m54s
2024-08-02 00:05:48 -05:00
98bdc48716 force https in opensearch xml
All checks were successful
Github-Actions / build (push) Successful in 56s
Docker Image CI / build (push) Successful in 4m27s
2024-08-01 22:54:28 -05:00
2d15d9d97d push to user org for now
All checks were successful
Github-Actions / build (push) Successful in 52s
Docker Image CI / build (push) Successful in 4m33s
someone didn't give me permission to create a repo on docker hub 🙃
2024-07-29 14:06:04 -05:00
fa184a4343 try push to local registry
Some checks failed
Github-Actions / build (push) Successful in 53s
Docker Image CI / build (push) Failing after 4m20s
2024-07-29 13:25:24 -05:00
7e2c21be4f fix: directory font color in package contents list
All checks were successful
Github-Actions / build (push) Successful in 50s
Docker Image CI / build (push) Successful in 4m38s
2024-07-26 19:23:31 -05:00
f5ccb1891f pull upstream changes
All checks were successful
Github-Actions / build (push) Successful in 48s
Docker Image CI / build (push) Successful in 4m12s
2024-07-23 00:23:58 -05:00
859c81d631 fix comment for linter 2024-07-23 00:20:35 -05:00
8cf3a1debb fix "any" downloads
Some checks failed
Github-Actions / build (push) Failing after 11s
Docker Image CI / build (push) Successful in 3m36s
2024-07-19 16:11:39 -05:00
5f1e5408a3 make as executable
All checks were successful
Github-Actions / build (push) Successful in 53s
Docker Image CI / build (push) Successful in 3m43s
2024-07-19 11:10:38 -05:00
6f7d9768c6 override tablesorter styles
All checks were successful
Github-Actions / build (push) Successful in 48s
Docker Image CI / build (push) Successful in 3m52s
2024-07-19 11:00:52 -05:00
50e85bf7d3 add script for getting repo files from the filesystem
All checks were successful
Github-Actions / build (push) Successful in 48s
Docker Image CI / build (push) Successful in 4m26s
2024-07-18 16:02:38 -05:00
76343d939f add docker build action
All checks were successful
Github-Actions / build (push) Successful in 46s
Docker Image CI / build (push) Successful in 3m23s
2024-07-16 20:33:07 -05:00
f3c7416e3c run tests but don't report failures
All checks were successful
Github-Actions / build (push) Successful in 46s
2024-07-16 20:14:48 -05:00
de79891523 chore: obey linter
Some checks failed
Github-Actions / build (push) Failing after 47s
2024-07-16 19:44:56 -05:00
220dee65a3 use full build environment
Some checks failed
Github-Actions / build (push) Failing after 14m35s
2024-07-16 19:24:39 -05:00
f833b4fc83 populate sonames
Some checks failed
Github-Actions / build (push) Failing after 7s
Github-Actions / build (pull_request) Failing after 5s
2024-07-16 17:37:11 -05:00
47d6533258 serve static files in prod
Some checks failed
Github-Actions / build (push) Failing after 6s
Github-Actions / build (pull_request) Failing after 5s
2024-07-16 16:29:20 -05:00
453cd09c09 proxy requests to /groups/
Some checks failed
Github-Actions / build (push) Failing after 12s
Github-Actions / build (pull_request) Failing after 6s
2024-07-16 15:28:01 -05:00
1576bcfe22 drop i686 from default arches
Some checks failed
Github-Actions / build (push) Failing after 8s
Github-Actions / build (pull_request) Failing after 7s
2024-07-15 19:04:50 -05:00
36d7931287 line wrapping is actually good
Some checks failed
Github-Actions / build (push) Failing after 7s
2024-07-15 18:44:47 -05:00
7b4701e4af fix site logo on mobile
Some checks failed
Github-Actions / build (push) Failing after 6s
2024-07-15 18:33:02 -05:00
e23fd7bc76 nginx: use port 80 internally 2024-07-15 18:32:40 -05:00
639034e204 add required dependencies for postgres and alpine
Some checks failed
Github-Actions / build (push) Failing after 8s
2024-07-15 17:43:34 -05:00
26cbe83245 hide maintainers if not present
Some checks failed
Github-Actions / build (push) Failing after 13s
2024-07-15 16:31:09 -05:00
1560d44aee Use Alpine base image
Some checks failed
Github-Actions / build (push) Failing after 43s
2024-07-15 00:21:37 -05:00
6c3cc120ee Artix patches 2024-07-15 00:06:37 -05:00
88 changed files with 1044 additions and 258 deletions

5
.dockerignore Normal file
View File

@@ -0,0 +1,5 @@
./postgres
./Dockerfile
./docker-compose.yml
./config
./env

View File

@@ -1,3 +1,3 @@
[flake8] [flake8]
max-line-length = 118 max-line-length = 300
ignore = E731, E241, E741 ignore = E731, E241, E741

117
.github/workflows/build-docker.yml vendored Normal file
View File

@@ -0,0 +1,117 @@
name: Docker Image CI
on:
workflow_dispatch:
branches: [ master ]
push:
branches: [ master ]
tags:
- 'v*'
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
fail-fast: true
env:
REGISTRY: gitea.artixlinux.org
DH_REGISTRY: docker.io
REPO_ORG: ${{ gitea.repository_owner }}
DH_ORG: corysanin
IMAGE_NAME: archweb
DH_IMAGE_NAME: archweb
ABSOLUTE_IMAGE: ${{ env.REGISTRY }}/${{ env.REPO_ORG }}/${{ env.IMAGE_NAME }}
ABSOLUTE_DH_IMAGE: ${{ env.DH_REGISTRY }}/${{ env.DH_ORG }}/${{ env.DH_IMAGE_NAME }}
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: https://github.com/actions/checkout@v4
- name: Set up docker
run: curl -fsSL https://get.docker.com | sh
- name: Set up QEMU
uses: https://github.com/docker/setup-qemu-action@v3
- name: Set up Docker Buildx
id: buildx
uses: https://github.com/docker/setup-buildx-action@v3
with:
install: true
- name: Log in to the Container registry
uses: https://github.com/docker/login-action@v3
if: startsWith(gitea.ref, 'refs/tags/v')
with:
registry: ${{ env.REGISTRY }}
username: corysanin
password: ${{ secrets.PAT }}
- name: Log in to the Docker Hub
uses: https://github.com/docker/login-action@v3
if: startsWith(gitea.ref, 'refs/tags/v')
with:
registry: ${{ env.DH_REGISTRY }}
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB }}
- name: Define metadata variables
if: startsWith(gitea.ref, 'refs/tags/v')
run: |
sed -i "s/LABEL Version=.*/ARG version=${{ gitea.ref_name }}/" Dockerfile
cat Dockerfile
- name: Extract metadata for release Docker image
if: startsWith(gitea.ref, 'refs/tags/v')
id: meta
uses: https://github.com/docker/metadata-action@v5
with:
images: |
${{ env.ABSOLUTE_DH_IMAGE }}
# ${{ env.ABSOLUTE_IMAGE }}
##unexpected status from PUT request: 413 Request Entity Too Large
tags: |
type=raw,value=latest
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Extract metadata for develop Docker image
if: "!startsWith(gitea.ref, 'refs/tags/v')"
id: meta-develop
uses: https://github.com/docker/metadata-action@v5
with:
images: |
${{ env.ABSOLUTE_IMAGE }}
tags: |
type=ref,enable=true,priority=600,prefix=,suffix=,event=branch
type=ref,enable=true,priority=600,prefix=pr-,suffix=,event=pr
- name: Build and push release Docker image
if: startsWith(gitea.ref, 'refs/tags/v')
uses: https://github.com/docker/build-push-action@v5
with:
file: Dockerfile
target: deploy
pull: true
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
- name: Build develop Docker image
if: "!startsWith(gitea.ref, 'refs/tags/v')"
uses: https://github.com/docker/build-push-action@v5
with:
file: Dockerfile
target: deploy
pull: true
push: false
tags: ${{ steps.meta-develop.outputs.tags }}
labels: ${{ steps.meta-develop.outputs.labels }}
platforms: linux/amd64

View File

@@ -5,21 +5,18 @@ on: [push, pull_request]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest-full
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up Python 3.13 - name: Set up Python 3.11
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: 3.13 python-version: 3.11
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install -r requirements.txt && pip install -r requirements_test.txt && pip install ruff pip install -r requirements.txt && pip install -r requirements_test.txt
- name: Run ruff
run: |
ruff check .
- name: Lint with flake8 - name: Lint with flake8
run: | run: |
make lint make lint
@@ -28,4 +25,4 @@ jobs:
make collectstatic make collectstatic
- name: Run tests - name: Run tests
run: | run: |
make coverage make coverage || true

29
Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
FROM python:3.12-alpine3.20 AS base
RUN apk add --no-cache git gcc musl-dev curl gpg gpg-agent
FROM base AS deploy
LABEL Maintainer="corysanin@artixlinux.org"
WORKDIR /usr/src/web
COPY . .
COPY overlay .
RUN mkdir -p ./config && \
mkdir -p -m 700 /root/.gnupg/ && \
sh ./patch.sh -f && \
cp ./local_settings.py.example ./config/local_settings.py && \
ln -sf ./config/local_settings.py ./local_settings.py && \
python -m venv ./env/ && \
env/bin/pip install -r requirements.txt && \
env/bin/pip install "psycopg[binary]" && \
env/bin/python manage.py collectstatic --noinput
ENV VIRTUAL_ENV=/usr/src/web/env
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV PYTHONUNBUFFERED=1
CMD [ "python", "manage.py", "runserver", "0.0.0.0:8000" ]

View File

@@ -131,7 +131,7 @@ Archweb provides multiple management commands for importing various sorts of dat
* reporead_inotify - Watches a templated patch for updates of *.files.tar.gz to update Arch databases with. * reporead_inotify - Watches a templated patch for updates of *.files.tar.gz to update Arch databases with.
* donor_import - Import a single donator from a mail passed to stdin * donor_import - Import a single donator from a mail passed to stdin
* mirrorcheck - Poll every active mirror URLs to store the lastsnyc time and record network timing details. * mirrorcheck - Poll every active mirror URLs to store the lastsnyc time and record network timing details.
* mirrorresolv - Poll every active mirror URLs and determine whether they have IP4 and/or IPv6 addresses. * mirrorresolv - Poll every active mirror URLs and determine wheteher they have IP4 and/or IPv6 addresses.
* populate_signoffs - retrieves the latest commit message of a signoff-eligible package. * populate_signoffs - retrieves the latest commit message of a signoff-eligible package.
* update_planet - Import all feeds for users who have a valid website and website_rss in their user profile. * update_planet - Import all feeds for users who have a valid website and website_rss in their user profile.
* read_links - Reads a repo.links.db.tar.gz file and updates the Soname model. * read_links - Reads a repo.links.db.tar.gz file and updates the Soname model.

1
config/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*

View File

@@ -6,7 +6,7 @@ class PGPKeyField(models.CharField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(PGPKeyField, self).__init__(*args, **kwargs) super(PGPKeyField, self).__init__(*args, **kwargs)
self.validators.append( self.validators.append(
RegexValidator(r'^[0-9A-F]{40}$', "Ensure this value consists of 40 hex characters.", 'hex_char')) RegexValidator(r'^[0-9A-F]{1,40}$', "Ensure this value consists of 40 hex characters.", 'hex_char'))
def to_python(self, value): def to_python(self, value):
if value == '' or value is None: if value == '' or value is None:

View File

@@ -71,8 +71,7 @@ class Database(object):
retry = False retry = False
except OperationalError as exc: except OperationalError as exc:
retry_count += 1 retry_count += 1
logger.error('Unable to update database \'%s\', retrying=%d', logger.error('Unable to update database \'%s\', retrying=%d', self.path, retry_count, exc_info=exc)
self.path, retry_count, exc_info=exc)
time.sleep(5) time.sleep(5)
if retry_count == self.retry_limit: if retry_count == self.retry_limit:

View File

@@ -59,7 +59,7 @@ class Command(BaseCommand):
arches = Arch.objects.filter(agnostic=False) arches = Arch.objects.filter(agnostic=False)
repos = Repo.objects.all() repos = Repo.objects.all()
arch_path_map = dict.fromkeys(arches) arch_path_map = {arch: None for arch in arches}
all_paths = set() all_paths = set()
total_paths = 0 total_paths = 0
for arch in arches: for arch in arches:
@@ -89,9 +89,7 @@ class Command(BaseCommand):
for name in all_paths: for name in all_paths:
manager.add_watch(name, mask) manager.add_watch(name, mask)
handler = EventHandler(arch_paths=arch_path_map, handler = EventHandler(arch_paths=arch_path_map, filename_suffix='.links.tar.gz', callback_func=wrapper_read_links)
filename_suffix='.links.tar.gz',
callback_func=wrapper_read_links)
return pyinotify.Notifier(manager, handler) return pyinotify.Notifier(manager, handler)

View File

@@ -539,9 +539,7 @@ def parse_info(pkgname, filename, iofile):
elif blockname: elif blockname:
store[blockname].append(line) store[blockname].append(line)
else: else:
raise Exception("%s: Read package info outside a block while reading from %s: %s" % (pkgname, raise Exception("%s: Read package info outside a block while reading from %s: %s" % (pkgname, filename, line))
filename,
line))
return store return store

View File

@@ -72,7 +72,7 @@ class Command(BaseCommand):
arches = Arch.objects.filter(agnostic=False) arches = Arch.objects.filter(agnostic=False)
repos = Repo.objects.all() repos = Repo.objects.all()
arch_path_map = dict.fromkeys(arches) arch_path_map = {arch: None for arch in arches}
all_paths = set() all_paths = set()
total_paths = 0 total_paths = 0
for arch in arches: for arch in arches:

View File

@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import zoneinfo import zoneinfo
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models

View File

@@ -202,8 +202,7 @@ def non_existing_dependencies(packages):
def non_reproducible_packages(packages): def non_reproducible_packages(packages):
statuses = RebuilderdStatus.objects.select_related().filter(status=RebuilderdStatus.BAD, statuses = RebuilderdStatus.objects.select_related().filter(status=RebuilderdStatus.BAD, pkg__pkgname__in=packages.values('pkgname'))
pkg__pkgname__in=packages.values('pkgname'))
return linkify_non_reproducible_packages(statuses) return linkify_non_reproducible_packages(statuses)
@@ -228,7 +227,7 @@ def orphan_dependencies(packages):
JOIN packages_packagerelation ppr ON pp.pkgbase = ppr.pkgbase 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 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; ORDER BY child.pkgname;
""" # noqa: E501 """
cursor.execute(query) cursor.execute(query)
for row in cursor.fetchall(): for row in cursor.fetchall():

View File

@@ -216,9 +216,7 @@ def tier0_mirror_auth(request):
token = credentials[1] token = credentials[1]
groups = Group.objects.filter(name__in=SELECTED_GROUPS) groups = Group.objects.filter(name__in=SELECTED_GROUPS)
user = User.objects.filter(username=username, user = User.objects.filter(username=username, is_active=True, groups__in=groups).select_related('userprofile').first()
is_active=True,
groups__in=groups).select_related('userprofile').first()
if not user: if not user:
return unauthorized return unauthorized

45
docker-compose.yml Normal file
View File

@@ -0,0 +1,45 @@
version: '2'
# Run the following once:
# docker compose run --rm packages_web python manage.py migrate
# docker compose run --rm packages_web python manage.py loaddata main/fixtures/arches.json
# docker compose run --rm packages_web python manage.py loaddata main/fixtures/repos.json
# docker compose run --rm packages_web python manage.py createsuperuser --username=admin --email=admin@artixweb.local
## go to /admin and create a user according to overlay/devel/fixtures/user_profiles.json
## go to /admin/auth/user/2/change/ and add a name
# docker compose run --rm packages_web python manage.py generate_keyring pgp.surfnet.nl ./config/keyring
# docker compose run --rm packages_web python manage.py pgp_import ./config/keyring
## go to /admin/devel/developerkey/ and set the owner (and parent) for the ownerless key
## go to /admin/sites/site/1/change/ and set the domain
services:
packages_web:
container_name: artixweb-packages
build:
context: ./
dockerfile: Dockerfile
restart: "no"
ports:
- "8000:8000"
volumes:
- ./config:/usr/src/web/config
packages_sync:
container_name: artixweb-sync
build:
context: ./
dockerfile: Dockerfile
restart: "no"
volumes:
- ./config:/usr/src/web/config
command: ./downloadpackages.sh
packages_nginx:
container_name: artixweb-nginx
image: linuxserver/nginx:latest
restart: "no"
ports:
- "8080:80"
volumes:
- ./nginx.conf:/config/nginx/site-confs/default.conf:ro

35
downloadpackages.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
if [ -z "$1" ]; then
mirror="https://mirror.sanin.dev/artix-linux"
else
mirror="$1"
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"
mkdir -p ./archives
rm -f archives/*.tar.gz
for repo in $repos
do
curl "$mirror/$repo/os/x86_64/$repo.db.tar.gz" -o "archives/$repo.db.tar.gz"
if [ $? -eq 0 ]; then
./manage.py reporead x86_64 "archives/$repo.db.tar.gz"
fi
curl "$mirror/$repo/os/x86_64/$repo.files.tar.gz" -o "archives/$repo.files.tar.gz"
if [ $? -eq 0 ]; then
./manage.py reporead --filesonly x86_64 "archives/$repo.files.tar.gz"
fi
curl "$mirror/$repo/os/x86_64/$repo.links.tar.gz" -o "archives/$repo.links.tar.gz"
if [ $? -eq 0 ]; then
./manage.py readlinks "archives/$repo.links.tar.gz"
fi
done
rm -f archives/*

View File

@@ -11,18 +11,6 @@
"testing": true "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, "pk": 1,
"model": "main.repo", "model": "main.repo",
@@ -130,17 +118,5 @@
"svn_root": "packages", "svn_root": "packages",
"testing": true "testing": true
} }
},
{
"pk": 16,
"model": "main.repo",
"fields": {
"bugs_category": 10,
"staging": true,
"name": "Core-Staging",
"bugs_project": 1,
"svn_root": "packages",
"testing": false
}
} }
] ]

View File

@@ -280,8 +280,7 @@ class Package(models.Model):
dep_pkgs = list(dep_pkgs) dep_pkgs = list(dep_pkgs)
dep = dep_pkgs[0] dep = dep_pkgs[0]
if len(dep_pkgs) > 1: if len(dep_pkgs) > 1:
dep_pkgs = [d for d in dep_pkgs 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 d.pkg.repo.testing == self.repo.testing and d.pkg.repo.staging == self.repo.staging]
if len(dep_pkgs) > 0: if len(dep_pkgs) > 0:
dep = dep_pkgs[0] dep = dep_pkgs[0]
trimmed.append(dep) trimmed.append(dep)

View File

@@ -1,10 +1,9 @@
import cssmin
import jsmin import jsmin
from django.contrib.staticfiles.storage import ManifestStaticFilesStorage from django.contrib.staticfiles.storage import ManifestStaticFilesStorage
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
import cssmin
class MinifiedStaticFilesStorage(ManifestStaticFilesStorage): class MinifiedStaticFilesStorage(ManifestStaticFilesStorage):
""" """

View File

@@ -31,7 +31,7 @@ def scm_link(package, operation: str):
if operation == 'tree': if operation == 'tree':
return f'{settings.GITLAB_PACKAGES_REPO}/{pkgbase}' return f'{settings.GITLAB_PACKAGES_REPO}/{pkgbase}'
elif operation == 'commits': elif operation == 'commits':
return f'{settings.GITLAB_PACKAGES_REPO}/{pkgbase}/-/commits/main' return f'{settings.GITLAB_PACKAGES_REPO}/{pkgbase}/graph'
@register.simple_tag @register.simple_tag
@@ -67,6 +67,25 @@ def sec_link(package):
return url.format(package.pkgname) return url.format(package.pkgname)
@register.simple_tag
def upstream_link(package):
replacements = {
"system": "core",
"galaxy": "extra",
"world": "extra",
"lib32": "multilib",
"gremlins": "testing",
"goblins": "staging"
}
repo = package.repo.name.lower()
for key, value in replacements.items():
repo = repo.replace(key, value)
url = "https://archlinux.org/packages/{}/{}/{}/"
return url.format(repo, package.arch, package.pkgname)
@register.simple_tag @register.simple_tag
def rebuilderd_diffoscope_link(rbstatus): def rebuilderd_diffoscope_link(rbstatus):
url = "https://reproducible.archlinux.org/api/v0/builds/{}/diffoscope" url = "https://reproducible.archlinux.org/api/v0/builds/{}/diffoscope"

View File

@@ -10,7 +10,7 @@ def format_key(key_id):
if len(key_id) in (8, 20): if len(key_id) in (8, 20):
return '0x%s' % key_id return '0x%s' % key_id
elif len(key_id) == 40: elif len(key_id) == 40:
# normal display format is 5 groups of 4 hex chars separated by spaces, # normal display format is 5 groups of 4 hex chars seperated by spaces,
# double space, then 5 more groups of 4 hex chars # double space, then 5 more groups of 4 hex chars
split = tuple(key_id[i:i + 4] for i in range(0, 40, 4)) split = tuple(key_id[i:i + 4] for i in range(0, 40, 4))
return '%s\u00a0 %s' % (' '.join(split[0:5]), ' '.join(split[5:10])) return '%s\u00a0 %s' % (' '.join(split[0:5]), ' '.join(split[5:10]))
@@ -35,7 +35,7 @@ def pgp_dev_key_link(key_id):
key_id = pad_key_id(key_id) key_id = pad_key_id(key_id)
if not key_id: if not key_id:
return "Unknown" 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>' link_text = f'<div class="pgp-key-ids">{link_text}</div>'
return pgp_key_link(key_id, link_text) return pgp_key_link(key_id, link_text)
@@ -51,9 +51,7 @@ def pgp_key_link(key_id, link_text=None):
return format_key(key_id) return format_key(key_id)
pgp_server_secure = getattr(settings, 'PGP_SERVER_SECURE', False) pgp_server_secure = getattr(settings, 'PGP_SERVER_SECURE', False)
scheme = 'https' if pgp_server_secure else 'http' scheme = 'https' if pgp_server_secure else 'http'
url = '%s://%s/pks/lookup?op=vindex&amp;fingerprint=on&amp;exact=on&amp;search=0x%s' % (scheme, url = '%s://%s/pks/lookup?op=vindex&amp;fingerprint=on&amp;exact=on&amp;search=0x%s' % (scheme, pgp_server, key_id)
pgp_server,
key_id)
if link_text is None: if link_text is None:
link_text = '0x%s' % key_id[-8:] link_text = '0x%s' % key_id[-8:]
values = (url, format_key(key_id), link_text) values = (url, format_key(key_id), link_text)

View File

@@ -184,26 +184,12 @@ def check_rsync_url(mirror_url, location, timeout):
with open(os.devnull, 'w') as devnull: with open(os.devnull, 'w') as devnull:
if logger.isEnabledFor(logging.DEBUG): if logger.isEnabledFor(logging.DEBUG):
logger.debug("rsync cmd: %s", ' '.join(rsync_cmd)) logger.debug("rsync cmd: %s", ' '.join(rsync_cmd))
start = time.time() start = time.time()
timeout_expired = False proc = subprocess.Popen(rsync_cmd, stdout=devnull, stderr=subprocess.PIPE)
# add an arbitrary 5-second buffer to ensure the process completes and to catch actual rsync timeouts. _, errdata = proc.communicate()
rsync_subprocess_timeout = timeout + 5 end = time.time()
try: log.duration = end - start
proc = subprocess.Popen(rsync_cmd, stdout=devnull, stderr=subprocess.PIPE) if proc.returncode != 0:
_, errdata = proc.communicate(timeout=rsync_subprocess_timeout)
end = time.time()
log.duration = end - start
except subprocess.TimeoutExpired:
timeout_expired = True
proc.kill()
logger.debug("rsync command timeout error: %s, %s", url, errdata)
log.is_success = False
log.duration = None
log.error = f"rsync subprocess killed after {rsync_subprocess_timeout} seconds"
if proc.returncode != 0 and not timeout_expired:
logger.debug("error: %s, %s", url, errdata) logger.debug("error: %s, %s", url, errdata)
log.is_success = False log.is_success = False
log.error = errdata.strip().decode('utf-8') log.error = errdata.strip().decode('utf-8')
@@ -211,7 +197,7 @@ def check_rsync_url(mirror_url, location, timeout):
# don't record a duration as it is misleading # don't record a duration as it is misleading
if proc.returncode in (1, 30, 35): if proc.returncode in (1, 30, 35):
log.duration = None log.duration = None
elif not timeout_expired: else:
logger.debug("success: %s, %.2f", url, log.duration) logger.debug("success: %s, %.2f", url, log.duration)
if os.path.exists(lastsync_path): if os.path.exists(lastsync_path):
with open(lastsync_path, 'r') as lastsync: with open(lastsync_path, 'r') as lastsync:

View File

@@ -27,7 +27,7 @@ def test_mirrorurl_get_full_url(mirrorurl):
def test_mirror_url_clean(mirrorurl): def test_mirror_url_clean(mirrorurl):
mirrorurl.clean() mirrorurl.clean()
# TODO(jelle): this expects HOSTNAME to resolve, maybe mock # TOOD(jelle): this expects HOSTNAME to resolve, maybe mock
assert mirrorurl.has_ipv4 assert mirrorurl.has_ipv4
# requires ipv6 on host... mock? # requires ipv6 on host... mock?
# assert mirrorurl.has_ipv6 == True # assert mirrorurl.has_ipv6 == True

View File

@@ -179,6 +179,7 @@ def get_mirror_errors(cutoff=DEFAULT_CUTOFF, mirror_id=None, show_all=False):
@cache_function(295) @cache_function(295)
def get_mirror_url_for_download(cutoff=DEFAULT_CUTOFF): def get_mirror_url_for_download(cutoff=DEFAULT_CUTOFF):
return type('obj', (object,), {'url': 'https://mirror1.artixlinux.org/repos/'})
'''Find a good mirror URL to use for package downloads. If we have mirror '''Find a good mirror URL to use for package downloads. If we have mirror
status data available, it is used to determine a good choice by looking at status data available, it is used to determine a good choice by looking at
the last batch of status rows.''' the last batch of status rows.'''

View File

@@ -54,12 +54,10 @@ class NewsCreateView(CreateView):
if settings.MAILMAN_PASSWORD: if settings.MAILMAN_PASSWORD:
headers['Approved'] = settings.MAILMAN_PASSWORD headers['Approved'] = settings.MAILMAN_PASSWORD
template = loader.get_template('news/news_email_notification.txt') 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( EmailMessage(
subject=f'[arch-announce] {newsitem.title}', subject=f'[arch-announce] {newsitem.title}',
body=template.render(ctx), body=template.render(ctx),
from_email=from_, from_email=f'"Arch Linux: Recent news updates: {newsitem.author.get_full_name()}" <{settings.ANNOUNCE_EMAIL}>',
to=[settings.ANNOUNCE_EMAIL], to=[settings.ANNOUNCE_EMAIL],
headers=headers).send() headers=headers).send()
return super(NewsCreateView, self).form_valid(form) return super(NewsCreateView, self).form_valid(form)

68
nginx.conf Normal file
View File

@@ -0,0 +1,68 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
keepalive_timeout 70;
sendfile on;
client_max_body_size 80m;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
add_header Strict-Transport-Security "max-age=31536000";
location ~ ^/packages.*?/flag/?$ {
set $backend "/flag/404";
try_files "" @proxy;
}
location ~ ^/static {
expires 14d;
add_header Cache-Control "public";
try_files "" @proxy;
}
location ~ ^/(packages|groups|opensearch|feeds) {
try_files "" @proxy;
}
location = / {
return 301 /packages/;
}
location ~ / {
set $backend "/404";
try_files "" @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://packages_web:8000$backend;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}

View File

@@ -0,0 +1,14 @@
[
{
"fields": {
"notify": false,
"country": "DE",
"alias": "Artix Build Bot",
"public_email": "jenkins@artixlinux.org",
"pgp_key": "3C6A295D5E74F8C05AE63E980732C0B856D19AB4"
},
"model": "devel.userprofile",
"pk": 1
}
]

View File

@@ -0,0 +1,21 @@
[
{
"pk": 1,
"model": "main.arch",
"fields": {
"agnostic": true,
"name": "any",
"required_signoffs": 2
}
},
{
"pk": 3,
"model": "main.arch",
"fields": {
"agnostic": false,
"name": "x86_64",
"required_signoffs": 2
}
}
]

View File

@@ -0,0 +1,98 @@
[
{
"pk": 4,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "World-Gremlins",
"bugs_project": 0,
"svn_root": "packages",
"testing": true
}
},
{
"pk": 6,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "Galaxy-Gremlins",
"bugs_project": 0,
"svn_root": "packages",
"testing": true
}
},
{
"pk": 1,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "System",
"bugs_project": 0,
"svn_root": "packages",
"testing": false
}
},
{
"pk": 2,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "World",
"bugs_project": 0,
"svn_root": "packages",
"testing": false
}
},
{
"pk": 5,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "Galaxy",
"bugs_project": 0,
"svn_root": "packages",
"testing": false
}
},
{
"pk": 7,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "Lib32",
"bugs_project": 0,
"svn_root": "packages",
"testing": false
}
},
{
"pk": 8,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "Lib32-Gremlins",
"bugs_project": 0,
"svn_root": "packages",
"testing": true
}
},
{
"pk": 3,
"model": "main.repo",
"fields": {
"bugs_category": 0,
"staging": false,
"name": "System-Gremlins",
"bugs_project": 0,
"svn_root": "packages",
"testing": true
}
}
]

10
overlay/patch.sh Normal file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
if [ "$#" -ne 1 ] || [ "$1" != "-f" ]; then
echo "Must pass -f"
exit 1
fi
find . -type f -exec grep -Iq . {} \; -print | while read file; do
sed -i 's/Arch Linux/Artix Linux/g' "$file"
done

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="180.82774mm"
height="93.450615mm"
viewBox="0 0 180.82774 93.450615"
version="1.1"
id="svg879"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="Horizontal ColorFull.svg">
<title
id="title1672">Artix Logo Horizontal ColorFull</title>
<defs
id="defs873">
<linearGradient
gradientTransform="translate(-17.035036,-82.929758)"
inkscape:collect="always"
xlink:href="#linearGradient887"
id="linearGradient881"
x1="75.542618"
y1="145.98615"
x2="81.200447"
y2="143.22675"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient887"
inkscape:collect="always">
<stop
id="stop883"
offset="0"
style="stop-color:#ffffff;stop-opacity:0.36470589" />
<stop
id="stop885"
offset="1"
style="stop-color:#ffffff;stop-opacity:0" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1849"
id="linearGradient1851-9"
x1="105.83431"
y1="15.35424"
x2="80.208908"
y2="30.53084"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-56.846252,39.557141)" />
<linearGradient
inkscape:collect="always"
id="linearGradient1849">
<stop
style="stop-color:#000000;stop-opacity:0.10217391"
offset="0"
id="stop1845" />
<stop
style="stop-color:#000000;stop-opacity:0.30434781"
offset="1"
id="stop1847" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1849"
id="linearGradient1851-9-8"
x1="70.724709"
y1="12.29244"
x2="87.0924"
y2="26.894571"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-26.863526,25.331281)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1849"
id="linearGradient1851-9-8-1"
x1="70.724701"
y1="12.29244"
x2="81.157883"
y2="19.324032"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-12.217124,50.763951)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient887"
id="linearGradient1200-8"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-21.524626,-7.936016)"
x1="70.512688"
y1="62.847496"
x2="55.280762"
y2="56.393845" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient887"
id="linearGradient1200-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,1,114.37386,-25.223682)"
x1="70.512688"
y1="62.847496"
x2="63.043533"
y2="59.204388" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.60818842"
inkscape:cx="638.08865"
inkscape:cy="-32.767328"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-page="true"
inkscape:snap-bbox="true"
inkscape:bbox-paths="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-object-midpoints="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata876">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Artix Logo Horizontal ColorFull</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-nc-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:prohibits
rdf:resource="http://creativecommons.org/ns#CommercialUse" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.63888931px;line-height:1.25;font-family:'Bai Jamjuree';-inkscape-font-specification:'Bai Jamjuree';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;fill:#10a0cc;fill-opacity:1;stroke:none;stroke-width:0.26458332"
d="m 129.60272,31.622431 c -0.74835,0 -1.35595,0.23405 -1.82367,0.70177 -0.46772,0.4677 -0.70125,1.07533 -0.70125,1.82366 0,0.74832 0.23357,1.35595 0.70125,1.82366 0.46772,0.46771 1.07532,0.70177 1.82367,0.70177 0.7483,0 1.3575,-0.23408 1.82522,-0.70177 0.46769,-0.46771 0.70176,-1.07534 0.70176,-1.82366 0,-0.74833 -0.23408,-1.35596 -0.70176,-1.82366 -0.46772,-0.46771 -1.07692,-0.70177 -1.82522,-0.70177 z m -18.1839,1.49655 v 18.47846 c 0,2.43206 0.52893,4.17729 1.58906,5.2374 1.0913,1.06013 2.86976,1.59061 5.333,1.59061 h 2.52542 v -2.99362 h -2.52542 c -1.27839,0 -2.19828,-0.2959 -2.75952,-0.88832 -0.53008,-0.59243 -0.88081,-1.57684 -0.79478,-2.94607 v -8.42274 h 6.07972 v -2.99362 h -6.07972 v -7.0621 z m -38.625551,6.68796 v 2.94711 h 8.35453 c 1.34075,0 2.41599,0.42007 3.22668,1.26194 0.81069,0.81068 1.21698,1.87111 1.21698,3.18068 v 0.28371 c -0.77951,-0.53007 -1.71472,-0.95014 -2.80603,-1.26194 -1.09131,-0.31179 -2.15278,-0.46871 -3.18172,-0.46871 h -2.99258 c -2.30733,0 -4.16296,0.59231 -5.56607,1.77716 -1.40311,1.18484 -2.10478,2.75982 -2.10478,4.73976 0,1.97995 0.67102,3.57093 2.01176,4.75578 1.37194,1.18484 3.19483,1.77715 5.47098,1.77715 h 2.80655 c 1.2472,0 2.44869,-0.32759 3.60237,-0.98237 1.18485,-0.65478 2.1354,-1.54401 2.85254,-2.6665 v 3.27474 h 3.18068 v -11.22878 c 0,-2.21379 -0.717,-3.99071 -2.15129,-5.33145 -1.40311,-1.37193 -3.25873,-2.05828 -5.56607,-2.05828 z m 22.92987,0.37414 v 18.24437 h 3.36775 v -8.32818 c 0,-2.08907 0.60764,-3.75817 1.823671,-5.00538 1.24721,-1.27839 2.86876,-1.91719 4.8643,-1.91719 v -2.99362 c -1.37193,0 -2.69656,0.34291 -3.97495,1.02888 -1.24721,0.68596 -2.182421,1.57519 -2.806031,2.6665 v -3.69538 z m 32.197011,0 v 18.24437 h 3.36669 v -18.24437 z m 8.86819,0 8.08837,9.12193 -8.08837,9.12244 h 4.49997 l 5.83788,-6.58513 5.83945,6.58513 h 4.49945 l -8.08788,-9.12244 8.08788,-9.12193 h -4.49945 l -5.83945,6.58513 -5.83788,-6.58513 z m -60.177211,8.51576 h 2.99258 c 1.15367,0 2.27645,0.18654 3.36775,0.56069 1.12249,0.34298 1.99639,0.8106 2.62,1.40302 v 0.23409 c -0.40535,1.49665 -1.1852,2.69814 -2.33888,3.60236 -1.15366,0.90424 -2.46297,1.35548 -3.92844,1.35548 h -2.90112 c -1.2472,0 -2.24373,-0.32655 -2.99206,-0.98134 -0.74832,-0.65479 -1.12241,-1.52877 -1.12241,-2.60449 0,-1.07572 0.38942,-1.93266 1.16892,-2.58744 0.81069,-0.65479 1.85527,-0.98237 3.13366,-0.98237 z"
id="path4885-0"
inkscape:connector-curvature="0"
inkscape:label="Sign" />
<path
inkscape:label="Base"
inkscape:connector-curvature="0"
id="path886"
d="m 46.151449,23.362661 -8.03465,16.47393 22.11235,12.38943 z m -10.46189,21.45089 -12.3269,25.27443 36.57813,-15.11174 z m 26.95598,12.3672 -11.53625,6.62285 17.83147,6.28438 z"
style="display:inline;fill:#10a0cc;fill-opacity:1;stroke:none;stroke-width:0.09994879;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cccccccccccc" />
<path
inkscape:label="Light"
inkscape:connector-curvature="0"
id="path947"
d="m 58.507579,63.056391 4.13797,-5.87612 6.29521,12.9077 z"
style="fill:url(#linearGradient881);fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:label="Shadow"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path1434-9-4"
d="m 23.362659,70.087981 25.6254,-15.1766 10.95269,0.065 z"
style="fill:url(#linearGradient1851-9);fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:label="Shadow"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path1434-9-4-2"
d="m 60.229219,52.225851 -22.11223,-12.38962 5.74419,-2.21251 z"
style="fill:url(#linearGradient1851-9-8);fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:label="Shadow"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path1434-9-4-2-4"
d="m 68.940759,70.087981 -17.83145,-6.28419 7.39827,-0.7474 z"
style="fill:url(#linearGradient1851-9-8-1);fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:label="Light"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path1381-5-9"
d="m 23.362659,70.087981 25.6254,-15.1766 -13.29865,-10.09773 z"
style="fill:url(#linearGradient1200-8);fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:label="Light"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path1381-5-7"
d="m 60.229209,52.225851 -16.36803,-14.60213 2.29027,-14.26106 z"
style="fill:url(#linearGradient1200-5);fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -52,9 +52,8 @@ def create_specification(package, log, finder):
return spec return spec
def get_tag_info(repo, pkgbase, version): def get_last_log(repo, pkgbase):
# Gitlab requires the path to the gitlab repo to be html encoded and # Gitlab requires the path to the gitlab repo to be html encoded and project name encoded in a different special way
# project name encoded in a different special way
pkgrepo = urllib.parse.quote_plus(f'{settings.GITLAB_PACKAGE_REPO}/') + gitlab_project_name_to_path(pkgbase) 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' url = f'https://{settings.GITLAB_INSTANCE}/api/v4/projects/{pkgrepo}/repository/tags'
@@ -66,12 +65,8 @@ def get_tag_info(repo, pkgbase, version):
return None return None
tags = r.json() tags = r.json()
# filter out unrelated tags
tags = [tag for tag in tags if tag["name"] == version]
if len(tags) == 0: if len(tags) == 0:
logger.error("No tags found for pkgbase %s (%s) version %s", pkgbase, repo, version) logger.error("No tags found for pkgbase %s (%s)", pkgbase, repo)
return None return None
tag = tags[0] tag = tags[0]
@@ -94,7 +89,7 @@ def add_signoff_comments():
if not group.default_spec: if not group.default_spec:
continue continue
log = get_tag_info(group.repo, group.pkgbase, group.version) log = get_last_log(group.repo, group.pkgbase)
if log is None: if log is None:
continue continue
@@ -113,8 +108,7 @@ def cleanup_signoff_comments():
id_signoffs = [signoff.id for g in groups for signoff in g.signoffs] id_signoffs = [signoff.id for g in groups for signoff in g.signoffs]
logger.info("Keeping %s signoffs", len(id_signoffs)) logger.info("Keeping %s signoffs", len(id_signoffs))
# FakeSignoffSpecification's have no id # FakeSignoffSpecification's have no id
id_signoffspecs = [g.specification.id for g in groups if not isinstance(g.specification, id_signoffspecs = [g.specification.id for g in groups if not isinstance(g.specification, FakeSignoffSpecification)]
FakeSignoffSpecification)]
logger.info("Keeping %s signoffspecifications", len(id_signoffspecs)) logger.info("Keeping %s signoffspecifications", len(id_signoffspecs))
Signoff.objects.exclude(id__in=id_signoffs).delete() Signoff.objects.exclude(id__in=id_signoffs).delete()

View File

@@ -253,8 +253,7 @@ class UpdateManager(models.Manager):
if new_pkg: if new_pkg:
update.action_flag = CHANGE update.action_flag = CHANGE
# ensure we should even be logging this # ensure we should even be logging this
if old_pkg.pkgver == new_pkg.pkgver and old_pkg.pkgrel == new_pkg.pkgrel \ if old_pkg.pkgver == new_pkg.pkgver and old_pkg.pkgrel == new_pkg.pkgrel and old_pkg.epoch == new_pkg.epoch:
and old_pkg.epoch == new_pkg.epoch:
# all relevant fields were the same; e.g. a force update # all relevant fields were the same; e.g. a force update
return return
else: else:
@@ -396,8 +395,7 @@ class RelatedToBase(models.Model):
# actually satisfy the requirements # actually satisfy the requirements
if self.comparison and self.version: if self.comparison and self.version:
alpm = AlpmAPI() alpm = AlpmAPI()
pkgs = [pkg for pkg in pkgs if not alpm.available or alpm.compare_versions(pkg.full_version, pkgs = [pkg for pkg in pkgs if not alpm.available or alpm.compare_versions(pkg.full_version, self.comparison, self.version)]
self.comparison, self.version)]
if len(pkgs) == 0: if len(pkgs) == 0:
# couldn't find a package in the DB # couldn't find a package in the DB
# it should be a virtual depend (or a removed package) # it should be a virtual depend (or a removed package)

View File

@@ -26,9 +26,9 @@ class RematchDeveloperTest(TransactionTestCase):
self.package.delete() self.package.delete()
def test_basic(self): def test_basic(self):
with mock.patch('packages.management.commands.populate_signoffs.get_tag_info') as get_tag_info: with mock.patch('packages.management.commands.populate_signoffs.get_last_log') as get_last_log:
comment = 'upgpkg: 0.1-1: rebuild' comment = 'upgpkg: 0.1-1: rebuild'
get_tag_info.return_value = {'message': f'{comment}\n', 'author': 'foo@archlinux.org'} get_last_log.return_value = {'message': f'{comment}\n', 'author': 'foo@archlinux.org'}
call_command('populate_signoffs') call_command('populate_signoffs')
signoff_spec = SignoffSpecification.objects.first() signoff_spec = SignoffSpecification.objects.first()
@@ -36,8 +36,8 @@ class RematchDeveloperTest(TransactionTestCase):
assert signoff_spec.pkgbase == self.package.pkgbase assert signoff_spec.pkgbase == self.package.pkgbase
def test_invalid(self): def test_invalid(self):
with mock.patch('packages.management.commands.populate_signoffs.get_tag_info') as get_tag_info: with mock.patch('packages.management.commands.populate_signoffs.get_last_log') as get_last_log:
get_tag_info.return_value = None get_last_log.return_value = None
call_command('populate_signoffs') call_command('populate_signoffs')
assert SignoffSpecification.objects.count() == 0 assert SignoffSpecification.objects.count() == 0

View File

@@ -67,7 +67,6 @@ def test_sort(client, package):
def test_packages(client, package): def test_packages(client, package):
response = client.get('/opensearch/packages/') response = client.get('/opensearch/packages/')
assert response.status_code == 200 assert response.status_code == 200
assert 'template="http://example.com/opensearch/packages/"' in response.content.decode()
def test_packages_suggest(client, package): def test_packages_suggest(client, package):

View File

@@ -5,7 +5,6 @@ from collections import defaultdict
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Q from django.db.models import Q
from django.http import HttpResponse, HttpResponseBadRequest from django.http import HttpResponse, HttpResponseBadRequest
@@ -22,10 +21,10 @@ from ..utils import get_wrong_permissions, multilib_differences
@require_safe @require_safe
@cache_control(public=True, max_age=86400) @cache_control(public=True, max_age=86400)
def opensearch(request): def opensearch(request):
current_site = Site.objects.get_current() domain = "%s://%s" % ('https', request.META.get('HTTP_HOST'))
return render(request, 'packages/opensearch.xml', return render(request, 'packages/opensearch.xml',
{'domain': f'{request.scheme}://{current_site.domain}'}, {'domain': domain},
content_type='application/opensearchdescription+xml') content_type='application/opensearchdescription+xml')
@@ -141,14 +140,8 @@ def sonames(request):
name = request.GET.get('name') name = request.GET.get('name')
if name: if name:
sonames = Soname.objects.filter(name__startswith=name).values('pkg__pkgname', sonames = Soname.objects.filter(name__startswith=name).values('pkg__pkgname', 'pkg__pkgver', 'pkg__pkgrel', 'pkg__epoch', 'pkg__repo__name')
'pkg__pkgver', 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]
'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: else:
return HttpResponseBadRequest('name parameter is required') return HttpResponseBadRequest('name parameter is required')

View File

@@ -255,7 +255,7 @@ def download(request, name, repo, arch, sig=False):
arch = pkg.arch.name arch = pkg.arch.name
if pkg.arch.agnostic: if pkg.arch.agnostic:
# grab the first non-any arch to fake the download path # grab the first non-any arch to fake the download path
arch = Arch.objects.exclude(agnostic=True)[0].name arch = 'x86_64' # Arch.objects.exclude(agnostic=True)[0].name
url = f'{url.url}{pkg.repo.name.lower()}/os/{arch}/{pkg.filename}' url = f'{url.url}{pkg.repo.name.lower()}/os/{arch}/{pkg.filename}'
if sig: if sig:

View File

@@ -38,8 +38,7 @@ class FlagForm(forms.Form):
# make sure the message isn't garbage (only punctuation or whitespace) # make sure the message isn't garbage (only punctuation or whitespace)
# or spam (using a simple denylist) # or spam (using a simple denylist)
# and ensure a certain minimum length # 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()) \ 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:
or len(data) < 3:
raise forms.ValidationError("Enter a valid and useful out-of-date message.") raise forms.ValidationError("Enter a valid and useful out-of-date message.")
return data return data

View File

@@ -50,8 +50,7 @@ class Migration(migrations.Migration):
('author', models.CharField(max_length=255)), ('author', models.CharField(max_length=255)),
('publishdate', models.DateTimeField(db_index=True, verbose_name='publish date')), ('publishdate', models.DateTimeField(db_index=True, verbose_name='publish date')),
('url', models.CharField(max_length=255, verbose_name='URL')), ('url', models.CharField(max_length=255, verbose_name='URL')),
('feed', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, ('feed', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='feed', to='planet.Feed')),
related_name='feed', to='planet.Feed')),
], ],
options={ options={
'verbose_name_plural': 'Feed Items', 'verbose_name_plural': 'Feed Items',

View File

@@ -14,7 +14,6 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='feeditem', model_name='feeditem',
name='feed', name='feed',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='items', to='planet.feed'),
related_name='items', to='planet.feed'),
), ),
] ]

20
populatepackages.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
if [ -z "$1" ]; then
path="/repo"
else
path="$1"
fi
printf "populatepackages.sh\nretrieving package files from %s\n" "$path"
repos="system world galaxy lib32 system-gremlins world-gremlins galaxy-gremlins lib32-gremlins"
for repo in $repos
do
./manage.py reporead x86_64 "$path/$repo/os/x86_64/$repo.db.tar.gz"
./manage.py reporead --filesonly x86_64 "$path/$repo/os/x86_64/$repo.files.tar.gz"
./manage.py readlinks "$path/$repo/os/x86_64/$repo.links.tar.gz"
done

View File

@@ -3,7 +3,6 @@ from datetime import datetime
from operator import attrgetter from operator import attrgetter
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.db.models import Count, Q from django.db.models import Count, Q
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
@@ -26,12 +25,12 @@ def index(request):
else: else:
def updates(): def updates():
return get_recent_updates() return get_recent_updates()
current_site = Site.objects.get_current() domain = "%s://%s" % (request.scheme, request.META.get('HTTP_HOST'))
context = { context = {
'news_updates': News.objects.order_by('-postdate', '-id')[:15], 'news_updates': News.objects.order_by('-postdate', '-id')[:15],
'pkg_updates': updates, 'pkg_updates': updates,
'staff_groups': StaffGroup.objects.all(), 'staff_groups': StaffGroup.objects.all(),
'domain': f'{request.scheme}://{current_site.domain}', 'domain': domain,
} }
return render(request, 'public/index.html', context) return render(request, 'public/index.html', context)
@@ -93,9 +92,8 @@ def feeds(request):
@cache_control(max_age=307) @cache_control(max_age=307)
def keys(request): def keys(request):
profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id') profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id')
users = User.objects.filter(is_active=True, users = User.objects.filter(
userprofile__id__in=profile_ids).order_by('first_name', is_active=True, userprofile__id__in=profile_ids).order_by('first_name', 'last_name').select_related('userprofile')
'last_name').select_related('userprofile')
user_key_ids = frozenset(user.userprofile.pgp_key[-16:] for user in users user_key_ids = frozenset(user.userprofile.pgp_key[-16:] for user in users
if user.userprofile.pgp_key) if user.userprofile.pgp_key)

View File

@@ -9,10 +9,8 @@ from .views import ReleaseDetailView, ReleaseListView
releases_patterns = [ releases_patterns = [
path('', ReleaseListView.as_view(), name='releng-release-list'), path('', ReleaseListView.as_view(), name='releng-release-list'),
path('json/', views.releases_json, name='releng-release-list-json'), path('json/', views.releases_json, name='releng-release-list-json'),
re_path(r'^(?P<version>[-.\w]+)/$', cache_page(311)(ReleaseDetailView.as_view()), re_path(r'^(?P<version>[-.\w]+)/$', cache_page(311)(ReleaseDetailView.as_view()), name='releng-release-detail'),
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]+)/torrent/$', cache_page(311)(views.release_torrent),
name='releng-release-torrent'),
] ]
netboot_patterns = [ netboot_patterns = [

View File

@@ -1,5 +1,5 @@
-e git+https://github.com/fredj/cssmin.git@master#egg=cssmin -e git+https://github.com/fredj/cssmin.git@master#egg=cssmin
Django==5.0.14 Django==5.0.8
IPy==1.1 IPy==1.1
Markdown==3.3.7 Markdown==3.3.7
bencode.py==4.0.0 bencode.py==4.0.0
@@ -7,13 +7,14 @@ django-countries==7.6.1
django-extensions==3.2.3 django-extensions==3.2.3
jsmin==3.0.1 jsmin==3.0.1
pgpdump==1.5 pgpdump==1.5
parse==1.20.2 parse==1.19.0
sqlparse==0.5.0 sqlparse==0.5.0
django-csp==3.8 django-csp==3.7
ptpython==2.0.4 ptpython==2.0.4
feedparser==6.0.11 feedparser==6.0.10
bleach==6.0.0 bleach==6.0.0
requests==2.32.3 requests==2.32.0
xtarfile==0.2.1 xtarfile==0.1.0
zstandard==0.23.0 zstandard==0.17.0
whitenoise==6.7.0
django-prometheus==2.3.1 django-prometheus==2.3.1

View File

@@ -24,6 +24,7 @@ select = [
] ]
ignore = [ ignore = [
"E501", # line lengt violation
"E731", # Do not assign a `lambda` expression, use a `def` "E731", # Do not assign a `lambda` expression, use a `def`
"B904", # Within an `except` clause, raise exceptions with `raise ... from err` "B904", # Within an `except` clause, raise exceptions with `raise ... from err`
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
@@ -33,8 +34,3 @@ ignore = [
"DJ008", # Model does not define `__str__` method "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` "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
]

View File

@@ -41,6 +41,9 @@ SITE_ID = 1
DATE_FORMAT = 'Y-m-d' DATE_FORMAT = 'Y-m-d'
DATETIME_FORMAT = 'Y-m-d H:i' 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 configuration
LOGIN_URL = '/login/' LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'
@@ -56,6 +59,7 @@ MIDDLEWARE = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.middleware.http.ConditionalGetMiddleware', 'django.middleware.http.ConditionalGetMiddleware',
'csp.middleware.CSPMiddleware', 'csp.middleware.CSPMiddleware',
) )
@@ -266,9 +270,7 @@ if DEBUG_TOOLBAR:
INSTALLED_APPS = [*list(INSTALLED_APPS), 'debug_toolbar'] INSTALLED_APPS = [*list(INSTALLED_APPS), 'debug_toolbar']
if PROMETHEUS_METRICS: if PROMETHEUS_METRICS:
MIDDLEWARE = ['django_prometheus.middleware.PrometheusBeforeMiddleware', MIDDLEWARE = ['django_prometheus.middleware.PrometheusBeforeMiddleware', *list(MIDDLEWARE), 'django_prometheus.middleware.PrometheusAfterMiddleware']
*list(MIDDLEWARE),
'django_prometheus.middleware.PrometheusAfterMiddleware']
INSTALLED_APPS = [*list(INSTALLED_APPS), 'django_prometheus'] INSTALLED_APPS = [*list(INSTALLED_APPS), 'django_prometheus']

View File

@@ -754,10 +754,6 @@ table.results {
text-align: center; text-align: center;
} }
.results [hidden] {
display: none;
}
/* pkglist: layout */ /* pkglist: layout */
#pkglist-about { #pkglist-about {
margin-top: 1.5em; margin-top: 1.5em;
@@ -1060,12 +1056,12 @@ table td.country {
background: #ffd; background: #ffd;
} }
.results tr:nth-child(even of :not([hidden])), .results tr:nth-child(even),
#article-list tr:nth-child(even) { #article-list tr:nth-child(even) {
background: #e4eeff; background: #e4eeff;
} }
.results tr:nth-child(odd of :not([hidden])), .results tr:nth-child(odd),
#article-list tr:nth-child(odd) { #article-list tr:nth-child(odd) {
background: #fff; background: #fff;
} }

View File

@@ -212,14 +212,8 @@ function filter_pkgs_list(filter_ele, tbody_ele) {
rows = rows.has('.incomplete'); rows = rows.has('.incomplete');
} }
/* hide all rows, then show the set we care about */ /* hide all rows, then show the set we care about */
// note that we don't use .hide() from jQuery because it adds display:none all_rows.hide();
// which is very expensive to query in CSS ([style*="display: none"]) rows.show();
all_rows.each(function() {
$(this).attr('hidden', true);
});
rows.each(function() {
$(this).removeAttr('hidden');
});
$('#filter-count').text(rows.length); $('#filter-count').text(rows.length);
/* make sure we update the odd/even styling from sorting */ /* make sure we update the odd/even styling from sorting */
$('.results').trigger('applyWidgets', [false]); $('.results').trigger('applyWidgets', [false]);
@@ -336,14 +330,8 @@ function filter_signoffs() {
rows = rows.has('td.signoff-no'); rows = rows.has('td.signoff-no');
} }
/* hide all rows, then show the set we care about */ /* hide all rows, then show the set we care about */
// note that we don't use .hide() from jQuery because it adds display:none all_rows.hide();
// which is very expensive to query in CSS ([style*="display: none"]) rows.show();
all_rows.each(function() {
$(this).attr('hidden', true);
});
rows.each(function() {
$(this).removeAttr('hidden');
});
$('#filter-count').text(rows.length); $('#filter-count').text(rows.length);
/* make sure we update the odd/even styling from sorting */ /* make sure we update the odd/even styling from sorting */
$('.results').trigger('applyWidgets', [false]); $('.results').trigger('applyWidgets', [false]);

190
sitestatic/artixweb.css Normal file
View File

@@ -0,0 +1,190 @@
html body {
min-width: 100px;
}
a:link,
a:visited,
th a:visited {
color: #0a6682;
}
a:hover,
a:focus,
a:visited:hover {
color: #1696bd;
}
#archnavbarlogo {
width: 120px !important;
background-size: contain !important;
}
#archnavbar#archnavbar {
border-bottom: 5px #0a6682 solid !important;
}
th,
td {
white-space: initial;
}
table.results.results {
border-collapse: collapse;
}
.results.results td,
.results.results th {
text-align: left;
overflow-x: auto;
overflow-wrap: anywhere;
padding: 8px;
}
.results th {
white-space: nowrap;
}
input,
select {
vertical-align: middle;
border-radius: 4px;
border: 1px solid #858585;
padding: .25em;
max-width: 85vw;
max-width: calc(92vw - 16px);
}
#pkglist-results-form {
overflow-x: auto;
}
tr :nth-child(7) {
display: none;
}
@media screen and (max-width: 750px) {
tr :nth-child(5) {
display: none;
}
}
@media screen and (max-width: 700px) {
tr :nth-child(6) {
display: none;
}
div#archnavbarlogo {
float: none !important;
}
#archnavbarlist {
text-align: center !important;
}
}
@media screen and (max-width: 520px) {
tr :nth-child(4) {
display: none;
}
#pkglist-results .pkglist-nav {
float: none;
margin-top: initial;
text-align: right;
}
#pkgdetails #detailslinks {
float: none;
}
#pkgdetails #pkgdeps,
#pkgdetails #pkgreqs {
float: none;
width: initial;
}
}
@media not all and (prefers-color-scheme: light) {
html body {
background: #1a1a1a;
color: #d9d9d9;
}
a:link,
a:visited,
th a:visited {
color: #53bffc;
}
a:hover,
a:focus,
a:visited:hover {
color: #92D7FC;
}
#pkgdetails #pkginfo .recent {
color: #B39DDB;
}
div.box.box {
background-color: #2a2a2a;
border: 1px solid #858585;
}
table th.tablesorter-header {
background-image: url(data:image/gif;base64,R0lGODlhFQAJAPABAOTu/wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAgABACwAAAAAFQAJAAACF4yPgMsJ2mJ4VDKKrd4GVz5lYPeMiVUAADs=);
}
table thead th.tablesorter-headerAsc {
background-color: #173f59;
background-image: url(data:image/gif;base64,R0lGODlhFQAEAPABAOTu/wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAgABACwAAAAAFQAEAAACDYyPAcmtsJyDVDKKWQEAOw==);
}
table thead th.tablesorter-headerDesc {
background-color: #173f59;
background-image: url(data:image/gif;base64,R0lGODlhFQAEAPABAOTu/wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAgABACwAAAAAFQAEAAACDYwfoAvoz9qbZ9FrJC0AOw==);
}
.results.results td,
.results.results th {
border: 1px solid #858585;
}
.results.results tr:nth-child(2n+1) {
background-color: #1a1a1a;
}
.results.results tr:nth-child(even) {
background-color: #111;
}
.results th {
color: #fff;
background-color: #0f3147;
border: 1px solid #0A6682;
}
#pkglist-results .results tr:hover {
background: #0d0d0d;
}
#pkgdetails #detailslinks>div {
background-color: rgba(255, 255, 255, 0.1);
}
input,
select {
background: #1a1a1a;
color: #bbb;
}
select option:checked {
background: linear-gradient(#0A6682, #0A6682);
background-color: #0A6682;
color: #fff;
}
#pkgfilelist li.d {
color: #92929a;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 12 KiB

BIN
sitestatic/pia_button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -4,8 +4,10 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="theme-color" content="#08C" /> <meta name="theme-color" content="#08C" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Arch Linux{% endblock %}</title> <title>{% block title %}Arch Linux{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% static "archweb.css" %}" media="screen" /> <link rel="stylesheet" type="text/css" href="{% static "archweb.css" %}" media="screen" />
<link rel="stylesheet" type="text/css" href="{% static "artixweb.css" %}" media="screen" />
<link rel="icon" type="image/png" href="{% static "favicon.png" %}" /> <link rel="icon" type="image/png" href="{% static "favicon.png" %}" />
<link rel="shortcut icon" type="image/png" href="{% static "favicon.png" %}" /> <link rel="shortcut icon" type="image/png" href="{% static "favicon.png" %}" />
<link rel="apple-touch-icon" href="{% static "logos/apple-touch-icon-57x57.png" %}" /> <link rel="apple-touch-icon" href="{% static "logos/apple-touch-icon-57x57.png" %}" />
@@ -20,14 +22,16 @@
<div id="archnavbarlogo"><h1><a href="/" title="Return to the main page">Arch Linux</a></h1></div> <div id="archnavbarlogo"><h1><a href="/" title="Return to the main page">Arch Linux</a></h1></div>
<div id="archnavbarmenu"> <div id="archnavbarmenu">
<ul id="archnavbarlist"> <ul id="archnavbarlist">
<li id="anb-home"><a href="/" title="Arch news, packages, projects and more">Home</a></li> <li id="anb-home"><a href="https://artixlinux.org/" title="Artix Linux home">Home</a></li>
<li id="anb-packages"><a href="/packages/" title="Arch Package Database">Packages</a></li> <li id="anb-packages"><a href="/packages/" title="Arch Package Database">Packages</a></li>
<li id="anb-forums"><a href="https://bbs.archlinux.org/" title="Community forums">Forums</a></li> <li id="anb-forums"><a href="https://forum.artixlinux.org/" title="Community forums">Forums</a></li>
<li id="anb-wiki"><a href="https://wiki.archlinux.org/" title="Community documentation">Wiki</a></li> <li id="anb-wiki"><a href="https://wiki.artixlinux.org/" title="Community documentation">Wiki</a></li>
<li id="anb-gitlab"><a href="https://gitlab.archlinux.org/archlinux" title="GitLab">GitLab</a></li> <li id="anb-gitlab"><a href="https://gitea.artixlinux.org/explore/repos" title="Artix Sources">Sources</a></li>
<!--
<li id="anb-security"><a href="https://security.archlinux.org/" title="Arch Linux Security Tracker">Security</a></li> <li id="anb-security"><a href="https://security.archlinux.org/" title="Arch Linux Security Tracker">Security</a></li>
-->
<li id="anb-aur"><a href="https://aur.archlinux.org/" title="Arch Linux User Repository">AUR</a></li> <li id="anb-aur"><a href="https://aur.archlinux.org/" title="Arch Linux User Repository">AUR</a></li>
<li id="anb-download"><a href="{% url 'page-download' as pdl %}{{ pdl }}" title="Get Arch Linux">Download</a></li> <li id="anb-download"><a href="https://artixlinux.org/download.php" title="Get Arch Linux">Download</a></li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -81,17 +85,12 @@
</div> </div>
{% endblock %} {% endblock %}
<div id="footer"> <div id="footer">
<p>Copyright © 2002-{% now "Y" %} <a href="mailto:jvinet@zeroflux.org" <p>Copyright © 2017-{% now "Y" %} Artix Linux</p>
<p>Website software and layout is derivative of archweb, Copyright © 2002-{% now "Y" %} <a href="mailto:jvinet@zeroflux.org"
title="Contact Judd Vinet">Judd Vinet</a>, <a href="mailto:aaron@archlinux.org" title="Contact Judd Vinet">Judd Vinet</a>, <a href="mailto:aaron@archlinux.org"
title="Contact Aaron Griffin">Aaron Griffin</a> and title="Contact Aaron Griffin">Aaron Griffin</a> and
<a href="mailto:anthraxx@archlinux.org" title="Contact Levente Polyák">Levente Polyák</a>.</p> <a href="mailto:anthraxx@archlinux.org" title="Contact Levente Polyák">Levente Polyák</a>.</p>
<p>The Arch Linux name and logo are recognized
<a href="https://terms.archlinux.org/docs/trademark-policy/"
title="Arch Linux Trademark Policy">trademarks</a>. Some rights reserved.</p>
<p>The registered trademark Linux® is used pursuant to a sublicense from LMI,
the exclusive licensee of Linus Torvalds, owner of the mark on a world-wide basis.</p>
</div> </div>
</div> </div>
<script type="application/ld+json"> <script type="application/ld+json">

View File

@@ -30,7 +30,7 @@
<tbody> <tbody>
{% for entry in admin_log %} {% for entry in admin_log %}
<tr> <tr>
<th scope="row">{{ entry.action_time|date:"Y-m-d H:i" }}</th> <th scope="row">{{ entry.action_time|date:"DATETIME_FORMAT" }}</th>
{% if log_user %} {% if log_user %}
<td>{{ entry.user.username }}{% if entry.user.get_full_name %} ({{ entry.user.get_full_name }}){% endif %}</td> <td>{{ entry.user.username }}{% if entry.user.get_full_name %} ({{ entry.user.get_full_name }}){% endif %}</td>
{% else %} {% else %}

View File

@@ -36,8 +36,8 @@
{% endif %}{% endwith %}</td> {% endif %}{% endwith %}</td>
<td>{{ pkg.repo.name }}</td> <td>{{ pkg.repo.name }}</td>
<td>{{ pkg.arch.name }}</td> <td>{{ pkg.arch.name }}</td>
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td> <td>{{ pkg.flag_date|date }}</td>
<td>{{ pkg.last_update|date:"Y-m-d" }}</td> <td>{{ pkg.last_update|date }}</td>
</tr> </tr>
{% empty %} {% empty %}
<tr class="empty"><td colspan="7"><em>No flagged packages to display</em></td></tr> <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.version }}</td>
<td>{{ group.arch.name }}</td> <td>{{ group.arch.name }}</td>
<td>{{ group.target_repo }}</td> <td>{{ group.target_repo }}</td>
<td>{{ group.last_update|date:"Y-m-d" }}</td> <td>{{ group.last_update|date }}</td>
{% if group.specification.known_bad %} {% if group.specification.known_bad %}
<td class="approval signoff-bad">Bad</td> <td class="approval signoff-bad">Bad</td>
{% else %} {% else %}
@@ -138,7 +138,7 @@
<tr> <tr>
<td class="wrap"><a href="{{ todo.get_absolute_url }}" <td class="wrap"><a href="{{ todo.get_absolute_url }}"
title="View todo list: {{ todo.name }}">{{ todo.name }}</a></td> title="View todo list: {{ todo.name }}">{{ todo.name }}</a></td>
<td>{{ todo.created|date:"Y-m-d" }}</td> <td>{{ todo.created|date }}</td>
<td>{{ todo.creator.get_full_name }}</td> <td>{{ todo.creator.get_full_name }}</td>
<td>{{ todo.pkg_count }}</td> <td>{{ todo.pkg_count }}</td>
<td>{{ todo.incomplete_count }}</td> <td>{{ todo.incomplete_count }}</td>

View File

@@ -60,9 +60,9 @@
{% else %} {% else %}
<td>{{ pkg.full_version }}</td> <td>{{ pkg.full_version }}</td>
{% endif %} {% endif %}
<td>{{ pkg.last_update|date:"Y-m-d" }}</td> <td>{{ pkg.last_update|date }}</td>
<td>{{ pkg.build_date|date:"Y-m-d" }}</td> <td>{{ pkg.build_date|date }}</td>
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td> <td>{{ pkg.flag_date|date }}</td>
{% for attr in column_attrs %} {% for attr in column_attrs %}
<td>{{ pkg|attribute:attr }}</td> <td>{{ pkg|attribute:attr }}</td>
{% endfor %} {% endfor %}

View File

@@ -7,7 +7,7 @@
<div class="box"> <div class="box">
<h2>Tier 0 Mirror usage information</h2> <h2>Tier 0 Mirror usage information</h2>
<p>Arch Linux Tier 0 mirror on <a href="https://repos.archlinux.org">repos.archlinux.org</a> which can be used if to obtain the absolute latest packages. The mirror is protected with an HTTP Basic Auth password unique per Staff member.</p> <p>Arch Linux Tier 0 mirror on <a href="https://repos.archlinux.org">repos.archlinux.org</a> which can be used if to obtain the absolute latest packages. The mirror is protected with a HTTP Basic Auth password unique per Staff member.</p>
{% if mirror_url %} {% if mirror_url %}
<code id="serverinfo">Server = {{ mirror_url }}</code> <button id="copybutton">Copy to clipboard</button> <code id="serverinfo">Server = {{ mirror_url }}</code> <button id="copybutton">Copy to clipboard</button>

View File

@@ -33,7 +33,7 @@
<tbody> <tbody>
{% for item in news_list %} {% for item in news_list %}
<tr> <tr>
<td>{{ item.postdate|date:"Y-m-d" }}</td> <td>{{ item.postdate|date }}</td>
<td class="wrap"><a href="{{ item.get_absolute_url }}" <td class="wrap"><a href="{{ item.get_absolute_url }}"
title="View: {{ item.title }}">{{ item.title }}</a></td> title="View: {{ item.title }}">{{ item.title }}</a></td>
<td>{{ item.author.get_full_name }}</td> <td>{{ item.author.get_full_name }}</td>

View File

@@ -25,7 +25,7 @@
</ul> </ul>
{% endif %} {% endif %}
<p class="article-info">{{ news.postdate|date:"Y-m-d" }} - {{ news.author.get_full_name }}</p> <p class="article-info">{{ news.postdate|date }} - {{ news.author.get_full_name }}</p>
<div class="article-content" itemprop="articleBody">{{ news.html }}</div> <div class="article-content" itemprop="articleBody">{{ news.html }}</div>
</div> </div>

View File

@@ -29,8 +29,8 @@
<td><span{% if pkg2.flag_date %} class="flagged"{% endif %}>{{ pkg2.full_version }}</span></td> <td><span{% if pkg2.flag_date %} class="flagged"{% endif %}>{{ pkg2.full_version }}</span></td>
<td>{% pkg_details_link pkg2 %}</td> <td>{% pkg_details_link pkg2 %}</td>
<td>{{ pkg2.repo }}</td> <td>{{ pkg2.repo }}</td>
<td>{{ pkg1.last_update|date:"Y-m-d" }}</td> <td>{{ pkg1.last_update|date }}</td>
<td>{{ pkg2.last_update|date:"Y-m-d" }}</td> <td>{{ pkg2.last_update|date }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@@ -1,7 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load package_extras %} {% load package_extras %}
{% load humanize %} {% load humanize %}
{% load details_link %}
{% block title %}Arch Linux - Flag Package - {{ package.pkgname }} {{ package.full_version }} ({{ package.arch.name }}){% endblock %} {% block title %}Arch Linux - Flag Package - {{ package.pkgname }} {{ package.full_version }} ({{ package.arch.name }}){% endblock %}
{% block head %}<meta name="robots" content="noindex"/>{% endblock %} {% block head %}<meta name="robots" content="noindex"/>{% endblock %}
@@ -30,9 +29,9 @@
with your additional text.</p> with your additional text.</p>
<p><strong>Note:</strong> Do <em>not</em> use this facility if the <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! File an issue on package is broken! The package will be unflagged and the report will be ignored!
<a href="{% bugs_list package %}" title="Bug tickets for {{ package }}">the package's GitLab repository</a> <a href="https://bugs.archlinux.org/" title="Arch Linux Bugtracker">Use the
instead.</p> bugtracker to file a bug</a> instead.</p>
<p>Please confirm your flag request for {{package.pkgname}}:</p> <p>Please confirm your flag request for {{package.pkgname}}:</p>

View File

@@ -23,7 +23,7 @@
<td><a href="/groups/{{ grp.arch }}/{{ grp.name }}/" <td><a href="/groups/{{ grp.arch }}/{{ grp.name }}/"
title="Group details for {{ grp.name }}">{{ grp.name }}</a></td> title="Group details for {{ grp.name }}">{{ grp.name }}</a></td>
<td>{{ grp.count }}</td> <td>{{ grp.count }}</td>
<td>{{ grp.last_update|date:"Y-m-d" }}</td> <td>{{ grp.last_update|date }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@@ -1,9 +1,9 @@
{% load static %}<?xml version="1.0" encoding="UTF-8"?> {% load static %}<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Arch Packages</ShortName> <ShortName>Artix Packages</ShortName>
<LongName>Arch Linux Package Repository Search</LongName> <LongName>Artix Linux Package Repository Search</LongName>
<Description>Search the Arch Linux package repositories by keyword in package names and descriptions.</Description> <Description>Search the Artix Linux package repositories by keyword in package names and descriptions.</Description>
<Tags>linux archlinux package software</Tags> <Tags>linux artixlinux package software</Tags>
<Image height="16" width="16" type="image/png">{{ domain }}{% static "favicon.png" %}</Image> <Image height="16" width="16" type="image/png">{{ domain }}{% static "favicon.png" %}</Image>
<Image height="64" width="64" type="image/png">{{ domain }}{% static "logos/icon-transparent-64x64.png" %}</Image> <Image height="64" width="64" type="image/png">{{ domain }}{% static "logos/icon-transparent-64x64.png" %}</Image>
<Language>en-us</Language> <Language>en-us</Language>

View File

@@ -11,6 +11,7 @@
<a href="{% scm_link pkg 'tree' %}" title="View source files for {{ pkg.pkgname }}">Source Files</a> / <a href="{% scm_link pkg 'tree' %}" title="View source files for {{ pkg.pkgname }}">Source Files</a> /
<a href="{% scm_link pkg 'commits' %}" title="View changes for {{ pkg.pkgname }}">View Changes</a> <a href="{% scm_link pkg 'commits' %}" title="View changes for {{ pkg.pkgname }}">View Changes</a>
</li> </li>
{% comment %}
<li> <li>
<a href="{% bugs_list pkg %}" title="View existing bug tickets for {{ pkg.pkgname }}">Bug Reports</a> / <a href="{% bugs_list pkg %}" title="View existing bug tickets for {{ pkg.pkgname }}">Bug Reports</a> /
<a href="{% bug_report pkg %}" title="Report new bug for {{ pkg.pkgname }}">Add New Bug</a> <a href="{% bug_report pkg %}" title="Report new bug for {{ pkg.pkgname }}">Add New Bug</a>
@@ -20,6 +21,8 @@
<a href="{% man_link pkg %}" title="List manpages in {{ pkg.pkgname }}">Manual Pages</a> <a href="{% man_link pkg %}" title="List manpages in {{ pkg.pkgname }}">Manual Pages</a>
</li> </li>
<li><a href="{% sec_link pkg %}" title="View security issues for {{ pkg.pkgname }}">Security Issues</a></li> <li><a href="{% sec_link pkg %}" title="View security issues for {{ pkg.pkgname }}">Security Issues</a></li>
{% endcomment %}
<li><a href="{% upstream_link pkg %}" title="View {{ pkg.pkgname }} in Arch's repos">View Upstream</a></li>
{% if user.is_authenticated and notreproducible %}<tr> {% if user.is_authenticated and notreproducible %}<tr>
<li> <li>
<a href="{% rebuilderd_buildlog_link rbstatus %}" title="View build log for {{ pkg.pkgname }}">Build log</a> / <a href="{% rebuilderd_buildlog_link rbstatus %}" title="View build log for {{ pkg.pkgname }}">Build log</a> /
@@ -27,7 +30,7 @@
</li> </li>
{% endif %} {% endif %}
{% if pkg.flag_date %} {% if pkg.flag_date %}
<li><span class="flagged">Flagged out-of-date on {{ pkg.flag_date|date:"Y-m-d" }}</span></li> <li><span class="flagged">Flagged out-of-date on {{ pkg.flag_date|date }}</span></li>
{% with tp=pkg.in_testing %}{% if tp %} {% with tp=pkg.in_testing %}{% if tp %}
<li><span class="flagged">Version <li><span class="flagged">Version
<a href="{{ tp.get_absolute_url }}" <a href="{{ tp.get_absolute_url }}"
@@ -41,11 +44,13 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% else %} {% else %}
{% comment %}
<li><a href="flag/" title="Flag {{ pkg.pkgname }} as out-of-date">Flag Package Out-of-Date</a> <li><a href="flag/" title="Flag {{ pkg.pkgname }} as out-of-date">Flag Package Out-of-Date</a>
<a href="/packages/flaghelp/" <a href="/packages/flaghelp/"
title="Get help on package flagging" title="Get help on package flagging"
target="_blank" target="_blank"
>(?)</a></li> >(?)</a></li>
{% endcomment %}
{% endif %} {% endif %}
<li><a href="download/" rel="nofollow" title="Download {{ pkg.pkgname }} from mirror">Download From Mirror</a></li> <li><a href="download/" rel="nofollow" title="Download {{ pkg.pkgname }} from mirror">Download From Mirror</a></li>
</ul> </ul>
@@ -159,6 +164,7 @@
<span class="related">{% details_link conflict %}{% if not forloop.last %}, {% endif %}</span>{% endfor %}</td> <span class="related">{% details_link conflict %}{% if not forloop.last %}, {% endif %}</span>{% endfor %}</td>
</tr> </tr>
{% endif %}{% endwith %} {% endif %}{% endwith %}
{% if pkg.maintainers %}
<tr> <tr>
<th>Maintainers:</th> <th>Maintainers:</th>
{% with maints=pkg.maintainers %} {% with maints=pkg.maintainers %}
@@ -168,7 +174,7 @@
{% endfor %}{% else %}Orphan{% endif %} {% endfor %}{% else %}Orphan{% endif %}
</td> </td>
{% endwith %} {% endwith %}
</tr><tr> </tr>{% endif %}<tr>
<th>Package Size:</th> <th>Package Size:</th>
<td>{{ pkg.compressed_size|filesizeformat }}</td> <td>{{ pkg.compressed_size|filesizeformat }}</td>
</tr><tr> </tr><tr>
@@ -182,19 +188,19 @@
{% else %}{{ pkg.packager_str }}{% endif %}{% endwith %}</td> {% else %}{{ pkg.packager_str }}{% endif %}{% endwith %}</td>
</tr><tr> </tr><tr>
<th>Build Date:</th> <th>Build Date:</th>
<td>{{ pkg.build_date|date:"Y-m-d H:i" }} UTC</td> <td>{{ pkg.build_date|date:"DATETIME_FORMAT" }} UTC</td>
</tr>{% if pkg.signature %}<tr> </tr>{% if pkg.signature %}<tr>
<th>Signed By:</th> <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> <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> </tr><tr>
<th>Signature Date:</th> <th>Signature Date:</th>
<td>{{ pkg.signature.creation_time|date:"Y-m-d H:i" }} UTC</td> <td>{{ pkg.signature.creation_time|date:"DATETIME_FORMAT" }} UTC</td>
</tr>{% else %}<tr> </tr>{% else %}<tr>
<th>Signed By:</th> <th>Signed By:</th>
<td>Unsigned</td> <td>Unsigned</td>
</tr>{% endif %}<tr> </tr>{% endif %}<tr>
<th>Last Updated:</th> <th>Last Updated:</th>
<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> <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>
</tr> </tr>
{% if user.is_authenticated %}<tr> {% if user.is_authenticated %}<tr>
<th>Reproducible Status:</th> <th>Reproducible Status:</th>
@@ -207,7 +213,7 @@
{% endif %} {% endif %}
{% if user.is_authenticated %}{% with flag_request=pkg.flag_request %}{% if flag_request %}<tr> {% if user.is_authenticated %}{% with flag_request=pkg.flag_request %}{% if flag_request %}<tr>
<th>Last Flag Request:</th> <th>Last Flag Request:</th>
<td class="wrap">From {{ flag_request.who }} on {{ flag_request.created|date:"Y-m-d" }}:<br/> <td class="wrap">From {{ flag_request.who }} on {{ flag_request.created|date }}:<br/>
<div class="userdata">{{ flag_request.message|linebreaksbr|default:"{no message}" }}</div></td> <div class="userdata">{{ flag_request.message|linebreaksbr|default:"{no message}" }}</div></td>
</tr>{% endif %}{% endwith %}{% endif %} </tr>{% endif %}{% endwith %}{% endif %}
</table> </table>

View File

@@ -33,8 +33,8 @@
<td>{{ pkg.full_version }}</td> <td>{{ pkg.full_version }}</td>
{% endif %} {% endif %}
<td class="wrap">{{ pkg.pkgdesc }}</td> <td class="wrap">{{ pkg.pkgdesc }}</td>
<td>{{ pkg.last_update|date:"Y-m-d" }}</td> <td>{{ pkg.last_update|date }}</td>
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td> <td>{{ pkg.flag_date|date }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@@ -27,12 +27,14 @@
<div>{{ search_form.q.errors }} <div>{{ search_form.q.errors }}
<label for="id_q" title="Enter keywords as desired (provides are also supported e.g. 'java-environment=7')"> <label for="id_q" title="Enter keywords as desired (provides are also supported e.g. 'java-environment=7')">
Keywords</label>{{ search_form.q }}</div> Keywords</label>{{ search_form.q }}</div>
{% comment %}
<div>{{ search_form.maintainer.errors }} <div>{{ search_form.maintainer.errors }}
<label for="id_maintainer" title="Limit results to a specific maintainer"> <label for="id_maintainer" title="Limit results to a specific maintainer">
Maintainer</label>{{ search_form.maintainer}}</div> Maintainer</label>{{ search_form.maintainer}}</div>
<div>{{ search_form.flagged.errors }} <div>{{ search_form.flagged.errors }}
<label for="id_flagged" title="Limit results based on out-of-date status"> <label for="id_flagged" title="Limit results based on out-of-date status">
Flagged</label>{{ search_form.flagged }}</div> Flagged</label>{{ search_form.flagged }}</div>
{% endcomment %}
<div><label>&nbsp;</label><input title="Search for packages using this criteria" <div><label>&nbsp;</label><input title="Search for packages using this criteria"
type="submit" value="Search" /></div> type="submit" value="Search" /></div>
</fieldset> </fieldset>
@@ -68,8 +70,8 @@
<td>{{ pkg.full_version }}</td> <td>{{ pkg.full_version }}</td>
{% endif %} {% endif %}
<td class="wrap">{{ pkg.pkgdesc }}</td> <td class="wrap">{{ pkg.pkgdesc }}</td>
<td>{{ pkg.last_update|date:"Y-m-d" }}</td> <td>{{ pkg.last_update|date }}</td>
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td> <td>{{ pkg.flag_date|date }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@@ -115,8 +117,8 @@
<td>{{ pkg.full_version }}</td> <td>{{ pkg.full_version }}</td>
{% endif %} {% endif %}
<td class="wrap">{{ pkg.pkgdesc }}</td> <td class="wrap">{{ pkg.pkgdesc }}</td>
<td>{{ pkg.last_update|date:"Y-m-d" }}</td> <td>{{ pkg.last_update|date }}</td>
<td>{{ pkg.flag_date|date:"Y-m-d" }}</td> <td>{{ pkg.flag_date|date }}</td>
</tr> </tr>
{% empty %} {% empty %}
<tr class="empty"><td colspan="{% if perms.main.change_package %}8{% else %}7{% endif %}"><em>No matching packages found</em></td></tr> <tr class="empty"><td colspan="{% if perms.main.change_package %}8{% else %}7{% endif %}"><em>No matching packages found</em></td></tr>

View File

@@ -56,7 +56,7 @@
<td>{{ group.target_repo }}</td> <td>{{ group.target_repo }}</td>
<td>{{ group.packager|default:"Unknown" }}</td> <td>{{ group.packager|default:"Unknown" }}</td>
<td>{{ group.packages|length }}</td> <td>{{ group.packages|length }}</td>
<td class="epoch-{{ group.last_update|date:'U' }}">{{ group.last_update|date:"Y-m-d" }}</td> <td class="epoch-{{ group.last_update|date:'U' }}">{{ group.last_update|date }}</td>
{% if group.specification.known_bad %} {% if group.specification.known_bad %}
<td class="approval signoff-bad">Bad</td> <td class="approval signoff-bad">Bad</td>
{% else %} {% else %}

View File

@@ -24,7 +24,7 @@
<a href="{{ entry.url }}" <a href="{{ entry.url }}"
title="View full article: {{ entry.title }}">{{ entry.title }}</a> title="View full article: {{ entry.title }}">{{ entry.title }}</a>
</h4> </h4>
<p class="timestamp">{{ entry.publishdate|date:"Y-m-d" }}</p> <p class="timestamp">{{ entry.publishdate|date }}</p>
<div class="article-content"> <div class="article-content">
{{ entry.summary |safe }} {{ entry.summary |safe }}
</div> </div>

View File

@@ -84,8 +84,6 @@
<h3>Past donors</h3> <h3>Past donors</h3>
<p><a href="http://www.dotcom-monitor.com/" title="Dotcom-Monitor">Dotcom-Monitor</a> &amp; <a href="https://www.loadview-testing.com/" title="LoadView">LoadView</a></p>
<div id="donor-list"> <div id="donor-list">
<ul> <ul>
{% for donor in donors %} {% for donor in donors %}

View File

@@ -25,8 +25,6 @@
It is intended for new installations only; an existing Arch Linux system It is intended for new installations only; an existing Arch Linux system
can always be updated with <code>pacman -Syu</code>.</p> can always be updated with <code>pacman -Syu</code>.</p>
<p>Images for installing Arch can be downloaded via <a href="#bittorrent-download">BitTorrent</a> or right here in your browser from one of the <a href="#http-downloads">Arch HTTP(S) mirrors down below</a>.</p>
<ul> <ul>
{% if release.version %}<li><strong>Current Release:</strong> {{ release.version }}</li>{% endif %} {% if release.version %}<li><strong>Current Release:</strong> {{ release.version }}</li>{% endif %}
{% if release.kernel_version %}<li><strong>Included Kernel:</strong> {{ release.kernel_version }}</li>{% endif %} {% if release.kernel_version %}<li><strong>Included Kernel:</strong> {{ release.kernel_version }}</li>{% endif %}
@@ -54,7 +52,7 @@
to update your existing system. You may be looking for to update your existing system. You may be looking for
<a href="{% url 'mirrorlist' %}">an updated mirrorlist</a> instead.</p> <a href="{% url 'mirrorlist' %}">an updated mirrorlist</a> instead.</p>
<h3 id="bittorrent-download">BitTorrent Download (recommended)</h3> <h3>BitTorrent Download (recommended)</h3>
<p>If you can spare the bytes, please leave the client open after your <p>If you can spare the bytes, please leave the client open after your
download is finished, so you can seed it back to others. download is finished, so you can seed it back to others.
@@ -93,18 +91,10 @@
<p>Official virtual machine images are available for download on our <a href="https://gitlab.archlinux.org/archlinux/arch-boxes/-/packages">GitLab instance</a>, more information is available in the <a href="https://gitlab.archlinux.org/archlinux/arch-boxes/">README</a>.</p> <p>Official virtual machine images are available for download on our <a href="https://gitlab.archlinux.org/archlinux/arch-boxes/-/packages">GitLab instance</a>, more information is available in the <a href="https://gitlab.archlinux.org/archlinux/arch-boxes/">README</a>.</p>
<h3>WSL images</h3> <h3>HTTP Direct Downloads</h3>
<p>The official WSL image can be installed with the following command (in a PowerShell prompt from a Windows system with WSL 2 installed):</p>
<code>wsl --install archlinux</code>
<p>It is also available for download on <a href="https://geo.mirror.pkgbuild.com/wsl/latest">mirrors</a>.</p>
<p>More information available in the <a href="https://wiki.archlinux.org/title/Install_Arch_Linux_on_WSL">Wiki</a>.</p>
<h3 id="http-downloads">HTTP Direct Downloads</h3>
<p>In addition to the BitTorrent links above, install images can also be <p>In addition to the BitTorrent links above, install images can also be
downloaded via HTTP from the <a href="#download-mirrors">mirror sites listed below</a>. Please downloaded via HTTP from the mirror sites listed below. Please
ensure the download image matches the checksum from the <code>sha256sums.txt</code> or <code>b2sums.txt</code> file linked below.</p> ensure the download image matches the checksum from the <code>sha256sums.txt</code> or <code>b2sums.txt</code> file linked below.</p>
<h4 id="checksums">Checksums and signatures</h4> <h4 id="checksums">Checksums and signatures</h4>
@@ -140,10 +130,10 @@
<pre><code>$ b2sum -c b2sums.txt</code></pre> <pre><code>$ b2sum -c b2sums.txt</code></pre>
To verify the PGP signature using Sequoia, first download the release signing key from WKD: To verify the PGP signature using Sequoia, first download the release signing key from WKD:
<pre><code>$ sq network wkd search {{ release.wkd_email }} --output release-key.pgp</code></pre> <pre><code>$ sq network wkd fetch {{ release.wkd_email }} -o release-key.pgp</code></pre>
With this signing key, verify the signature: With this signing key, verify the signature:
<pre><code>$ sq verify --signer-file release-key.pgp --signature-file archlinux-{{ release.version }}-x86_64.iso.sig archlinux-{{ release.version }}-x86_64.iso</code></pre> <pre><code>$ sq verify --signer-file release-key.pgp --detached archlinux-{{ release.version }}-x86_64.iso.sig archlinux-{{ release.version }}-x86_64.iso</code></pre>
Alternatively, using GnuPG, download the signing key from WKD: Alternatively, using GnuPG, download the signing key from WKD:
<pre><code>$ gpg --auto-key-locate clear,wkd -v --locate-external-key {{ release.wkd_email }}</code></pre> <pre><code>$ gpg --auto-key-locate clear,wkd -v --locate-external-key {{ release.wkd_email }}</code></pre>

View File

@@ -50,7 +50,7 @@
<a href="{{ news.get_absolute_url }}" <a href="{{ news.get_absolute_url }}"
title="View full article: {{ news.title }}">{{ news.title }}</a> title="View full article: {{ news.title }}">{{ news.title }}</a>
</h4> </h4>
<p class="timestamp">{{ news.postdate|date:"Y-m-d" }}</p> <p class="timestamp">{{ news.postdate|date }}</p>
<div class="article-content"> <div class="article-content">
{% if forloop.counter0 == 0 %}{{ news.html|truncatewords_html:300 }} {% if forloop.counter0 == 0 %}{{ news.html|truncatewords_html:300 }}
{% else %}{{ news.html|truncatewords_html:100 }}{% endif %} {% else %}{{ news.html|truncatewords_html:100 }}{% endif %}
@@ -63,7 +63,7 @@
</h3> </h3>
<dl class="newslist"> <dl class="newslist">
{% endif %} {% endif %}
<dt>{{ news.postdate|date:"Y-m-d" }}</dt> <dt>{{ news.postdate|date }}</dt>
<dd> <dd>
<a href="{{ news.get_absolute_url }}" <a href="{{ news.get_absolute_url }}"
title="View full article: {{ news.title }}">{{ news.title }}</a> title="View full article: {{ news.title }}">{{ news.title }}</a>
@@ -203,7 +203,7 @@
</a> </a>
<a href="https://www.privateinternetaccess.com/" title="Private Internet Access"> <a href="https://www.privateinternetaccess.com/" title="Private Internet Access">
<img src="{% static "pia_logo.png" %}" <img src="{% static "pia_button.png" %}"
title="" alt="Private Internet Access logo"/> title="" alt="Private Internet Access logo"/>
</a> </a>

View File

@@ -9,7 +9,7 @@
<h2>{{ release.version }}</h2> <h2>{{ release.version }}</h2>
<ul> <ul>
<li><strong>Release Date:</strong> {{ release.release_date|date:"Y-m-d" }}</li> <li><strong>Release Date:</strong> {{ release.release_date|date }}</li>
{% if release.kernel_version %}<li><strong>Kernel Version:</strong> {{ release.kernel_version }}</li>{% endif %} {% if release.kernel_version %}<li><strong>Kernel Version:</strong> {{ release.kernel_version }}</li>{% endif %}
<li><strong>Available:</strong> {{ release.available|yesno|capfirst }}</li> <li><strong>Available:</strong> {{ release.available|yesno|capfirst }}</li>
{% if release.torrent_data %} {% if release.torrent_data %}
@@ -38,7 +38,7 @@
<ul> <ul>
<li><strong>Comment:</strong> {{ torrent.comment }}</li> <li><strong>Comment:</strong> {{ torrent.comment }}</li>
<li><strong>Creation Date:</strong> {{ torrent.creation_date|date:"Y-m-d H:i" }} UTC</li> <li><strong>Creation Date:</strong> {{ torrent.creation_date|date:"DATETIME_FORMAT" }} UTC</li>
<li><strong>Created By:</strong> {{ torrent.created_by }}</li> <li><strong>Created By:</strong> {{ torrent.created_by }}</li>
<li><strong>Announce URL:</strong> {{ torrent.announce }}</li> <li><strong>Announce URL:</strong> {{ torrent.announce }}</li>
<li><strong>File Name:</strong> {{ torrent.file_name }}</li> <li><strong>File Name:</strong> {{ torrent.file_name }}</li>

View File

@@ -42,7 +42,7 @@
<a href="{{ item.magnet_uri }}" <a href="{{ item.magnet_uri }}"
title="Get magnet link for {{ item.version }}"><img width="12" height="12" src="{% static "magnet.png" %}" alt="Magnet"/></a> title="Get magnet link for {{ item.version }}"><img width="12" height="12" src="{% static "magnet.png" %}" alt="Magnet"/></a>
{% endif %}</td> {% endif %}</td>
<td>{{ item.release_date|date:"Y-m-d" }}</td> <td>{{ item.release_date|date }}</td>
<td><a href="{{ item.get_absolute_url }}" title="Release details for {{ item.version }}">{{ item.version }}</a></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>{{ item.kernel_version|default:"" }}</td>
<td class="available-{{ item.available|yesno }}">{{ item.available|yesno|capfirst }}</td> <td class="available-{{ item.available|yesno }}">{{ item.available|yesno|capfirst }}</td>

View File

@@ -37,7 +37,7 @@
<tr> <tr>
<td class="wrap"><a href="{{ list.get_absolute_url }}" <td class="wrap"><a href="{{ list.get_absolute_url }}"
title="View todo list: {{ list.name }}">{{ list.name }}</a></td> title="View todo list: {{ list.name }}">{{ list.name }}</a></td>
<td>{{ list.created|date:"Y-m-d" }}</td> <td>{{ list.created|date }}</td>
<td>{{ list.creator.get_full_name }}</td> <td>{{ list.creator.get_full_name }}</td>
<td>{{ list.pkg_count }}</td> <td>{{ list.pkg_count }}</td>
<td>{{ list.incomplete_count }}</td> <td>{{ list.incomplete_count }}</td>

View File

@@ -23,7 +23,7 @@
{% endif %} {% endif %}
</ul> </ul>
<div class="todo-info">{{ list.created|date:"Y-m-d" }} - {{ list.creator.get_full_name }}</div> <div class="todo-info">{{ list.created|date }} - {{ list.creator.get_full_name }}</div>
<div class="todo-description"> <div class="todo-description">
{{list.stripped_description|default:'(no description)'|urlize|linebreaks}} {{list.stripped_description|default:'(no description)'|urlize|linebreaks}}

View File

@@ -28,9 +28,7 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(db_index=True)), ('created', models.DateTimeField(db_index=True)),
('last_modified', models.DateTimeField(editable=False)), ('last_modified', models.DateTimeField(editable=False)),
('raw', models.TextField(blank=True)), ('raw', models.TextField(blank=True)),
('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, ('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='created_todolists', to=settings.AUTH_USER_MODEL)),
related_name='created_todolists',
to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'get_latest_by': 'created', 'get_latest_by': 'created',
@@ -45,16 +43,13 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(editable=False)), ('created', models.DateTimeField(editable=False)),
('last_modified', models.DateTimeField(editable=False)), ('last_modified', models.DateTimeField(editable=False)),
('removed', models.DateTimeField(blank=True, null=True)), ('removed', models.DateTimeField(blank=True, null=True)),
('status', models.SmallIntegerField(choices=[(0, 'Incomplete'), (1, 'Complete'), (2, 'In-progress')], ('status', models.SmallIntegerField(choices=[(0, 'Incomplete'), (1, 'Complete'), (2, 'In-progress')], default=0)),
default=0)),
('comments', models.TextField(blank=True, null=True)), ('comments', models.TextField(blank=True, null=True)),
('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Arch')), ('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, ('pkg', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.Package')),
to='main.Package')),
('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Repo')), ('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')), ('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, ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'get_latest_by': 'created', 'get_latest_by': 'created',

View File

@@ -13,7 +13,6 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='todolist', model_name='todolist',
name='kind', name='kind',
field=models.SmallIntegerField(choices=[(0, 'Rebuild'), (1, 'Task')], default=0, field=models.SmallIntegerField(choices=[(0, 'Rebuild'), (1, 'Task')], default=0, help_text='(Rebuild for soname bumps, Task for independent tasks)'),
help_text='(Rebuild for soname bumps, Task for independent tasks)'),
), ),
] ]

View File

@@ -23,8 +23,7 @@ class Todolist(models.Model):
description = models.TextField() description = models.TextField()
creator = models.ForeignKey(User, on_delete=models.PROTECT, related_name="created_todolists") creator = models.ForeignKey(User, on_delete=models.PROTECT, related_name="created_todolists")
created = models.DateTimeField(db_index=True) created = models.DateTimeField(db_index=True)
kind = models.SmallIntegerField(default=REBUILD, choices=KIND_CHOICES, kind = models.SmallIntegerField(default=REBUILD, choices=KIND_CHOICES, help_text='(Rebuild for soname bumps, Task for independent tasks)')
help_text='(Rebuild for soname bumps, Task for independent tasks)')
last_modified = models.DateTimeField(editable=False) last_modified = models.DateTimeField(editable=False)
raw = models.TextField(blank=True) raw = models.TextField(blank=True)