Branches are simple, but more complex than head

I used to think branches were simple when it came to FreshPorts, but I was wrong. Consider slave ports for example.

If we get a commit for databases/mariadb100-server, we have to update the slave ports, but only the slave ports on the branch, not the slave ports on head.

That sounds easy enough, but keep in mind that FreshPorts only knows about ports which have had a commit. If the first commit is to the master port, then there is no slave port on the branch for FreshPorts.

But wait, you’ll think, the branch is just a branch and it’s a copy of the repo from at the time the branch was … branched, the slave port is always there.

Well, yes, in the repo, but FreshPorts is not a copy of the repo, it is a reflection of commits and that data is extracted via make -V (for the most part).

When that commit for databases/mariadb100-server, there might not be any ports on the branch which have it as a master port. However, there might be commits on other branches, which means the existing SQL might return something like this:

SELECT PA.id          AS slave_port_id,
       PA.name        AS slave_port_name,
       PA.category_id AS slave_category_id,
       PA.category    AS slave_category_name,
       element_pathname(EP.element_id)
  FROM ports_active PA, element_pathname EP
 WHERE PA.master_port = 'databases/mariadb100-server'
   AND PA.element_id  = EP.element_id;

 slave_port_id |  slave_port_name  | slave_category_id | slave_category_name |                  element_pathname                  
---------------+-------------------+-------------------+---------------------+----------------------------------------------------
         35630 | mariadb100-client |                32 | databases           | /ports/head/databases/mariadb100-client
         40269 | mariadb100-client |                32 | databases           | /ports/branches/2015Q3/databases/mariadb100-client
         41023 | mariadb100-client |                32 | databases           | /ports/branches/2015Q4/databases/mariadb100-client
(3 rows)

As you can see, we have three different slave ports, none of which are on our branch (which is this particular case, is 2016Q2.

I think we need to have a query which takes the path into consideration, so we get only the slave ports on our branch. For example:

SELECT PA.id          AS slave_port_id,
       PA.name        AS slave_port_name,
       PA.category_id AS slave_category_id,
       PA.category    AS slave_category_name,
       element_pathname(EP.element_id)
  FROM ports_active PA, element_pathname EP
 WHERE PA.master_port = 'databases/mariadb100-server'
   AND EP.pathname    ilike '/ports/branches/2016Q2/%'
   AND PA.element_id  = EP.element_id;

 slave_port_id | slave_port_name | slave_category_id | slave_category_name | element_pathname 
---------------+-----------------+-------------------+---------------------+------------------
(0 rows)

This is correct. However, it is not ideal for our purposes. We want a list of ports, whether or not they are already on our branch.

Union to the rescue.

SELECT PA.id          AS slave_port_id,
       PA.name        AS slave_port_name,
       PA.category_id AS slave_category_id,
       PA.category    AS slave_category_name,
       element_pathname(EP.element_id)
  FROM ports_active PA, element_pathname EP
 WHERE PA.master_port = 'databases/mariadb100-server'
   AND EP.pathname    ilike '/ports/branches/2016Q2/%'
   AND PA.element_id  = EP.element_id

UNION

SELECT PA.id          AS slave_port_id,
       PA.name        AS slave_port_name,
       PA.category_id AS slave_category_id,
       PA.category    AS slave_category_name,
       element_pathname(EP.element_id)
  FROM ports_active PA, element_pathname EP
 WHERE PA.master_port = 'databases/mariadb100-server'
   AND EP.pathname    ilike '/ports/head/%'
   AND PA.element_id  = EP.element_id

ORDER BY slave_category_name, slave_port_name;

 slave_port_id |  slave_port_name  | slave_category_id | slave_category_name |            element_pathname             
---------------+-------------------+-------------------+---------------------+-----------------------------------------
         35630 | mariadb100-client |                32 | databases           | /ports/head/databases/mariadb100-client
(1 row)

Now we have the list we need, and it will be clear which ports do not exist on the branch and we must first create the port instead of fetching it. This point becomes clearer when you try the same query on databases/postgresql94-server

SELECT PA.id          AS slave_port_id,
       PA.name        AS slave_port_name,
       PA.category_id AS slave_category_id,
       PA.category    AS slave_category_name,
       element_pathname(EP.element_id)
  FROM ports_active PA, element_pathname EP
 WHERE PA.master_port = 'databases/postgresql94-server'
   AND EP.pathname    ilike '/ports/branches/%'
   AND PA.element_id  = EP.element_id
UNION

SELECT PA.id          AS slave_port_id,
       PA.name        AS slave_port_name,
       PA.category_id AS slave_category_id,
       PA.category    AS slave_category_name,
       element_pathname(EP.element_id)
  FROM ports_active PA, element_pathname EP
 WHERE PA.master_port = 'databases/postgresql94-server'
   AND EP.pathname    ilike '/ports/head/%'
   AND PA.element_id  = EP.element_id
ORDER BY slave_category_name, slave_port_name, element_pathname;

 slave_port_id |    slave_port_name    | slave_category_id | slave_category_name |                   element_pathname                   
---------------+-----------------------+-------------------+---------------------+------------------------------------------------------
         40432 | postgresql94-client   |                32 | databases           | /ports/branches/2015Q2/databases/postgresql94-client
         39921 | postgresql94-client   |                32 | databases           | /ports/branches/2016Q1/databases/postgresql94-client
         34655 | postgresql94-client   |                32 | databases           | /ports/head/databases/postgresql94-client
         34657 | postgresql94-contrib  |                32 | databases           | /ports/head/databases/postgresql94-contrib
         34678 | postgresql94-docs     |                32 | databases           | /ports/head/databases/postgresql94-docs
         34677 | postgresql94-plperl   |                32 | databases           | /ports/head/databases/postgresql94-plperl
         34675 | postgresql94-plpython |                32 | databases           | /ports/head/databases/postgresql94-plpython
         34676 | postgresql94-pltcl    |                32 | databases           | /ports/head/databases/postgresql94-pltcl
(8 rows)

If you look only at slave_port_name and slave_category_name, you can see we have duplicates. The ideal situation takes values from head first, then removes any values found in the branch we are interested in, and for this query, we are interested in just one branch.

I’m positive we can do this with just one query.

I thought about this issue overnight. I think the solution is as follows.

  1. Get the list of master ports from head
  2. Look for those same port names on the branch
  3. If the port exists, confirm it still has the same master port (i.e. the one from step #1)
  4. If not the same same master port, ignore this ‘slave’ port
  5. If port exists, refresh it
  6. If port does not exist on branch, create it, and refresh it

NOTE:

  • Unless otherwise mentioned, we are dealing with the branch upon with the commit occurred
  • When refreshing, we refer to the commit we are processing now

I’ll have to think about this some more.

Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive

Leave a Comment

Scroll to Top