FreshPorts / freshports

The website part of FreshPorts
http://www.freshports.org/
BSD 2-Clause "Simplified" License
68 stars 24 forks source link

Sort package names by version, not the way it is done now #568

Closed dlangille closed 4 days ago

dlangille commented 4 months ago

Please provide PHP code which sorts the following strings in the order listed:

  1. py27-Jinja2
  2. py37-Jinja2
  3. py39-Jinja2
  4. py311-Jinja2

From https://www.freshports.org/devel/py-Jinja2/#packages we have:

Screenshot 2024-09-09 at 3 28 40 PM
rnelson commented 4 months ago

I was bored, so here's a starting point for someone far less rusty with PHP than myself:

<?php

// Tested on PHP 8.2.18 via OnlinePHP.io, PHP 7.4 on OpenBSD 7.5

function jinja_sort($arr) {
    $splits = array();
    $result = array();

    foreach ($arr as $item) {
        $halves = preg_split('/-/', $item);
        $runtimeBits = preg_split('/(?<=\D)(?=\d)|(?<=\d)(?=\D)/', $halves[0], PREG_SPLIT_DELIM_CAPTURE);

        $splits[] = array('prefix' => $runtimeBits[0], 'runtime' => $runtimeBits[1], 'separator' => '-', 'lib' => $halves[1]);
    }

    asort($splits);

    foreach ($splits as $idx => $split) {
        $result[] = $splits[$idx]['prefix'] . $splits[$idx]['runtime'] . $splits[$idx]['separator'] . $splits[$idx]['lib'];
    }

    return $result;
}

print_r(jinja_sort(array('py39-Jinja2', 'py27-Jinja2', 'py37-Jinja2', 'py311-Jinja2')));

/*
Array
(
    [0] => py27-Jinja2
    [1] => py37-Jinja2
    [2] => py39-Jinja2
    [3] => py311-Jinja2
)
*/
dlangille commented 3 weeks ago

Works here:

[19:30 dvl-nginx01 dvl ~] % php ~/tmp/sorting.php
Array
(
    [0] => py27-Jinja2
    [1] => py37-Jinja2
    [2] => py39-Jinja2
    [3] => py311-Jinja2
)

I also like how it works with any prefix (i.e. I tried it with php instead of py - works as expected.

dlangille commented 3 weeks ago

I'll work on this part: We have a problem when the package name contains two dashes.

print_r(jinja_sort(array('py310-flit-core', 'py311-flit-core', 'py37-flit-core', 'py38-flit-core', 'py39-flit-core')));

Gives

Array
(
    [0] => py37-flit
    [1] => py38-flit
    [2] => py39-flit
    [3] => py310-flit
    [4] => py311-flit
)
dlangille commented 3 weeks ago

This change fixes that:

#        $halves = preg_split('/-/', $item);
        $halves = explode('-', $item, 2);

re:

Array
(
    [0] => py37-flit-core
    [1] => py38-flit-core
    [2] => py39-flit-core
    [3] => py310-flit-core
    [4] => py311-flit-core
)
dlangille commented 3 weeks ago

Here's what I have now, with a special case for ports which use python and do not use PYTHON_PKGNAMEPREFIX

//
// From https://github.com/FreshPorts/freshports/issues/568
// Written by https://github.com/rnelson
//
function pkg_prefix_sort($arr) {
    $splits = array();
    $result = array();

    foreach ($arr as $item) {
        $halves = explode('-', $item, 2);
        $runtimeBits = preg_split('/(?<=\D)(?=\d)|(?<=\d)(?=\D)/', $halves[0], PREG_SPLIT_DELIM_CAPTURE);

        # I hope to avoid this situtation by not calling this function when there is only one package available.        
        # we get caught up by ports like lang/python, which uses python (`make -V USES` gives python:run, similarly for lang/python39
        # but there is no PYTHON_PKGNAMEPREFIX in use... hence, I added this check:
        if (count($runtimeBits) <= 2) {
          return $arr;
        }

        $splits[] = array('prefix' => $runtimeBits[0], 'runtime' => $runtimeBits[1], 'separator' => '-', 'lib' => $halves[1]);
    }

    asort($splits);

    foreach ($splits as $idx => $split) {
        $result[] = $splits[$idx]['prefix'] . $splits[$idx]['runtime'] . $splits[$idx]['separator'] . $splits[$idx]['lib'];
    }

    return $result;
}
dlangille commented 3 weeks ago

@rnelson merge request created. It might show why I needed that special case added in.

rnelson commented 3 weeks ago

Yeah, makes perfect sense. It's been a few years since I've written any real amount of PHP that I forgot explode() exists. Glad it works!

dlangille commented 3 weeks ago

Packaged, deployed to dev, test, and stage. Not yet on prod.

dlangille commented 3 weeks ago

Now it is failing on my personal site, as well as dev. I must have mangled the merge. I'll come back to this.

dlangille commented 3 weeks ago

I fixed it - that clever if (count($runtimeBits) <= 2) { bit broke things for devel/py-Jinja2 - reverted.

dlangille commented 3 weeks ago

Now in production. Look ok to you @rnelson ?

rnelson commented 2 weeks ago

Looks good! 👍

dlangille commented 4 days ago

@rnelson thank you for the code