Skip to content

Commit

Permalink
gentoo client support
Browse files Browse the repository at this point in the history
  • Loading branch information
furlongm committed Feb 8, 2025
1 parent 3b5a983 commit d3b29a4
Show file tree
Hide file tree
Showing 11 changed files with 459 additions and 101 deletions.
31 changes: 31 additions & 0 deletions client/patchman-client
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,17 @@ get_installed_archlinux_packages() {
fi
}

get_installed_gentoo_packages() {
if check_command_exists qlist ; then
qlist -Ic -F "'%{PN}' '%{SLOT}' '%{PV}' REL'%{PR}' 'any' 'gentoo' '%{CAT}' '%{REPO}'" | sed -e "s/REL'r/'/g" >> "${tmpfile_pkg}"
fi
}

get_packages() {
get_installed_rpm_packages
get_installed_deb_packages
get_installed_archlinux_packages
get_installed_gentoo_packages
}

get_modules() {
Expand Down Expand Up @@ -346,6 +353,8 @@ get_host_data() {
os="${PRETTY_NAME}"
elif [ "${ID}" == "arch" ] ; then
os="${NAME}"
elif [ "${ID}" == "gentoo" ] ; then
os="${NAME}"
elif [[ "${ID}" =~ "suse" ]] ; then
os="${PRETTY_NAME}"
elif [ "${ID}" == "astra" ] ; then
Expand Down Expand Up @@ -557,6 +566,28 @@ get_repos() {
done
fi

# Gentoo
if [ "${os}" == "Gentoo" ] ; then
if [ ${verbose} == 1 ] ; then
echo 'Finding portage repos...'
fi
declare -A repos
repos[gentoo]='-1000'
repos_conf=$(awk '/\[/{prefix=$0; next} $1{print prefix $0}' /etc/portage/repos.conf/*.conf | grep '^\[')
for stanza in ${repos_conf} ; do
repo=$(echo ${stanza} | cut -d ']' -f 1 | sed -e 's/\[//')
rhs=$(echo ${stanza} | cut -d ']' -f 2 | grep -v '^#')
if [[ ${rhs} =~ "priority" ]] ; then
priority=$(echo ${rhs} | sed -e 's/^ *priority *= *//')
repos[${repo}]+=${priority}
unset priority
fi
done
for r in "${!repos[@]}"; do
echo "'gentoo' 'Gentoo Linux ${r} ${host_arch}' '${r}' '${repos[${r}]}'" >> "${tmpfile_rep}"
done
fi

IFS=${FULL_IFS}

sed -i -e '/^$/d' "${tmpfile_rep}"
Expand Down
11 changes: 7 additions & 4 deletions hosts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,13 @@ def find_host_repo_updates(self, host_packages, repo_packages):
priority = best_repo.priority

# find the packages that are potential updates
pu_q = Q(name=package.name,
arch=package.arch,
packagetype=package.packagetype)
potential_updates = repo_packages.filter(pu_q)
pu_q = Q(
name=package.name,
arch=package.arch,
packagetype=package.packagetype,
category=package.category,
)
potential_updates = repo_packages.filter(pu_q).exclude(version__startswith='9999')
for pu in potential_updates:
pu_is_module_package = False
pu_in_enabled_modules = False
Expand Down
36 changes: 36 additions & 0 deletions packages/migrations/0002_auto_20250207_1319.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 3.2.25 on 2025-02-07 13:19

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('packages', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='PackageCategory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
],
options={
'verbose_name': 'Package Category',
'verbose_name_plural': 'Package Categories',
'ordering': ('name',),
},
),
migrations.AlterField(
model_name='package',
name='packagetype',
field=models.CharField(blank=True, choices=[('R', 'rpm'), ('D', 'deb'), ('A', 'arch'), ('G', 'gentoo'), ('U', 'unknown')], max_length=1, null=True),
),
migrations.AddField(
model_name='package',
name='category',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='packages.packagecategory'),
),
]
18 changes: 18 additions & 0 deletions packages/migrations/0003_auto_20250207_1746.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.25 on 2025-02-07 17:46

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('arch', '0001_initial'),
('packages', '0002_auto_20250207_1319'),
]

operations = [
migrations.AlterUniqueTogether(
name='package',
unique_together={('name', 'epoch', 'version', 'release', 'arch', 'packagetype', 'category')},
),
]
52 changes: 36 additions & 16 deletions packages/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,32 @@ def get_absolute_url(self):
return reverse('packages:package_detail', args=[self.name])


class PackageCategory(models.Model):

name = models.CharField(unique=True, max_length=255)

class Meta:
verbose_name = 'Package Category'
verbose_name_plural = 'Package Categories'
ordering = ('name',)

def __str__(self):
return self.name


class Package(models.Model):

RPM = 'R'
DEB = 'D'
ARCH = 'A'
GENTOO = 'G'
UNKNOWN = 'U'

PACKAGE_TYPES = (
(RPM, 'rpm'),
(DEB, 'deb'),
(ARCH, 'arch'),
(GENTOO, 'gentoo'),
(UNKNOWN, 'unknown'),
)

Expand All @@ -63,19 +78,16 @@ class Package(models.Model):
version = models.CharField(max_length=255)
release = models.CharField(max_length=255, blank=True, null=True)
arch = models.ForeignKey(PackageArchitecture, on_delete=models.CASCADE)
packagetype = models.CharField(max_length=1,
choices=PACKAGE_TYPES,
blank=True,
null=True)
packagetype = models.CharField(max_length=1, choices=PACKAGE_TYPES, blank=True, null=True)
category = models.ForeignKey(PackageCategory, blank=True, null=True, on_delete=models.SET_NULL)
description = models.TextField(blank=True, null=True)
url = models.URLField(max_length=255, blank=True, null=True)

objects = PackageManager()

class Meta:
ordering = ('name', 'epoch', 'version', 'release', 'arch')
unique_together = (
'name', 'epoch', 'version', 'release', 'arch', 'packagetype',)
unique_together = ('name', 'epoch', 'version', 'release', 'arch', 'packagetype', 'category')

def __str__(self):
if self.epoch:
Expand All @@ -86,14 +98,16 @@ def __str__(self):
rel = f'-{self.release!s}'
else:
rel = ''
return f'{self.name!s}-{epo!s}{self.version!s}{rel!s}-{self.arch!s}'
if self.packagetype == 'G':
return f'{self.category!s}/{self.name!s}-{epo!s}{self.version!s}{rel!s}-{self.arch!s}'
else:
return f'{self.name!s}-{epo!s}{self.version!s}{rel!s}-{self.arch!s}'

def get_absolute_url(self):
return self.name.get_absolute_url()

def __key(self):
return (self.name, self.epoch, self.version, self.release, self.arch,
self.packagetype)
return (self.name, self.epoch, self.version, self.release, self.arch, self.packagetype, self.category)

def __eq__(self, other):
return self.__key() == other.__key()
Expand Down Expand Up @@ -122,7 +136,7 @@ def _version_string_deb_arch(self):
return (epoch + version + release)

def get_version_string(self):
if self.packagetype == 'R':
if self.packagetype == 'R' or self.packagetype == 'G':
return self._version_string_rpm()
elif self.packagetype == 'D' or self.packagetype == 'A':
return self._version_string_deb_arch()
Expand All @@ -143,6 +157,9 @@ def compare_version(self, other):
vs = Version(self.get_version_string())
vo = Version(other.get_version_string())
return version_compare(vs, vo)
elif self.packagetype == 'G' and other.packagetype == 'G':
return labelCompare(self.get_version_string(),
other.get_version_string())

def repo_count(self):
from repos.models import Repository
Expand All @@ -152,18 +169,19 @@ def repo_count(self):

class PackageString(models.Model):

class Meta:
managed = False

name = models.CharField(max_length=255)
version = models.CharField(max_length=255)
epoch = models.CharField(max_length=255, blank=True, null=True)
release = models.CharField(max_length=255, blank=True, null=True)
arch = models.CharField(max_length=255)
packagetype = models.CharField(max_length=1, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, null=True)
description = models.TextField(blank=True, null=True)
url = models.URLField(max_length=255, blank=True, null=True)

class Meta:
managed = False

def __str__(self):
if self.epoch:
epo = f'{self.epoch!s}:'
Expand All @@ -173,11 +191,13 @@ def __str__(self):
rel = f'-{self.release!s}'
else:
rel = ''
return f'{self.name!s}-{epo!s}{self.version!s}{rel!s}-{self.arch!s}'
if self.packagetype == 'G':
return f'{self.category!s}/{self.name!s}-{epo!s}{self.version!s}{rel!s}-{self.arch!s}'
else:
return f'{self.name!s}-{epo!s}{self.version!s}{rel!s}-{self.arch!s}'

def __key(self):
return (self.name, self.epoch, self.version, self.release, self.arch,
self.packagetype)
return (self.name, self.epoch, self.version, self.release, self.arch, self.packagetype, self.category)

def __eq__(self, other):
return self.__key() == other.__key()
Expand Down
54 changes: 52 additions & 2 deletions packages/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,62 @@
from django.db import IntegrityError, DatabaseError, transaction

from util import bunzip2, get_url, download_url, get_sha1
from packages.models import ErratumReference, PackageName, \
Package, PackageUpdate
from packages.models import ErratumReference, PackageName, Package, PackageUpdate, PackageCategory, PackageString
from arch.models import MachineArchitecture, PackageArchitecture
from patchman.signals import error_message, progress_info_s, progress_update_s


def convert_package_to_packagestring(package):
""" Convert a Package object to a PackageString object
"""
name = package.name.name
arch = package.arch.name
if package.category:
category = package.category.name
else:
category = None

string_package = PackageString(
name=name,
epoch=package.epoch,
version=package.version,
release=package.release,
arch=arch,
packagetype=package.packagetype,
category=category,
)
return string_package


def convert_packagestring_to_package(strpackage):
""" Convert a PackageString object to a Package object
"""
with transaction.atomic():
name, created = PackageName.objects.get_or_create(name=strpackage.name.lower())
epoch = strpackage.epoch
version = strpackage.version
release = strpackage.release
with transaction.atomic():
arch, created = PackageArchitecture.objects.get_or_create(name=strpackage.arch)
packagetype = strpackage.packagetype
if strpackage.category:
with transaction.atomic():
category, created = PackageCategory.objects.get_or_create(name=strpackage.category)
else:
category = None

package, created = Package.objects.get_or_create(
name=name,
epoch=epoch,
version=version,
release=release,
arch=arch,
packagetype=packagetype,
category=category,
)
return package


def find_evr(s):
""" Given a package version string, return the epoch, version, release
"""
Expand Down
Loading

0 comments on commit d3b29a4

Please sign in to comment.