Jul 292020
 

I spent an evening working through the delete issue with git repos.

A Twitter thread was the result.

Sergey Kozlov came up with some code changes which changed the XML output. Now I think we have a plan.

The commit I’m using for a working example was to editors/nvi2 on 27 Jul 2020 01:58:34 – the details of the git and svn commits are outlined below.

The svn commit

  1. The email
  2. The files part of the XML:
    <FILE Action="Add" Revision="543502" Path="head/editors/nvi2/"></FILE>
    <FILE Path="head/editors/nvi2-port/" Action="Remove" Revision="543502"></FILE>
    <FILE Path="head/editors/Makefile" Action="Modify" Revision="543502"></FILE>
    

The git commit

  1. There is no email
  2. The files part of the git XML:
    <FILE Action="Modify" Path="editors/Makefile"/>
    <FILE Action="Rename" Path="editors/nvi2-port/Makefile" Destination="editors/nvi2/Makefile"/>
    <FILE Action="Rename" Path="editors/nvi2-port/distinfo" Destination="editors/nvi2/distinfo"/>
    <FILE Action="Rename" Path="editors/nvi2-port/pkg-descr" Destination="editors/nvi2/pkg-descr"/>
    

The crucial difference

The svn XML shows head/editors/nvi2-port being Removed. As demonstrated via Twitter, this Removed action causes this SQL:

insert into commit_log_elements(id, commit_log_id, element_id, revision_name, change_type) values (4113357, 809907, 1063362, '543502', 'R')

That element_id value represents:

freshports.dev=# select element_pathname(1063362);
       element_pathname        
-------------------------------
/ports/head/editors/nvi2-port

That ‘R‘ on the insert to the commit_log_element table invoked this trigger action:

   if (NEW.change_type = 'R') then
      UPDATE element
         SET status = 'D'
       WHERE id = NEW.element_id;
   end if;

That marks the file (actually, a directory /ports/head/editors/nvi2-port) in the database. That’s the element table. What about the ports table? How does that happen.

How?

The above trigger deletes the element. The element table implements a directory and file using a recursive structure. In part, it looks like this:

freshports.dev=# \d element
                                     Table "public.element"
       Column        |     Type     | Collation | Nullable |               Default               
---------------------+--------------+-----------+----------+-------------------------------------
 id                  | integer      |           | not null | nextval('element_id_seq'::regclass)
 name                | text         |           | not null | 
 parent_id           | integer      |           |          | 
 directory_file_flag | character(1) |           | not null | 
 status              | character(1) |           | not null | 

As the commit is processed, the element (/ports/head/editors/nvi2-port) is deleted because of line 1 of the svn XML (head/editors/nvi2). In general terms, a port is an abstraction of the file system. As that part of the file system is deleted, the port must also be deleted, but that’s a separate table.

So how does the port get deleted? I’m now writing this in hindsight. I didn’t know that when I was posting to Twitter, but tonight I re-discovered it.

It is a trigger on the element table:

element_ports_status AFTER UPDATE ON element FOR EACH ROW EXECUTE FUNCTION element_ports_status()

It’s been many years since I wrote this. Checking the repo, I find it was committed on Mon Sep 11 02:27:26 2006 – I recall this was how it was done, but I’d completely forgotten about it.

-- keep ports.status in sync with element.status
-- this is a performance boosting exercise

CREATE OR REPLACE FUNCTION element_ports_status() RETURNS TRIGGER AS $$
   BEGIN
      IF (NEW.status <> OLD.status) then
         UPDATE ports
            SET status = NEW.status
          WHERE ports.element_id = NEW.id;
      END IF;
      RETURN NEW;
   END
$$ LANGUAGE 'plpgsql';

There it is. So long as I delete the directory which pertains to this port, the system will automagically, via triggers, delete the port.

What needs to change

With the git XML, we don’t get to see the directory being deleted (or removed, as the case may be).

I think we will have to make due with the port‘s Makefile being Remove‘d (in the svn XML) (or Rename‘d as shown in the git XML).

Rename or remove?

We have two options with the git library:

  1. <FILE Action="Rename" Path="editors/nvi2-port/Makefile" Destination="editors/nvi2/Makefile"/>
    <FILE Action="Rename" Path="editors/nvi2-port/distinfo" Destination="editors/nvi2/distinfo"/>
    <FILE Action="Rename" Path="editors/nvi2-port/pkg-descr" Destination="editors/nvi2/pkg-descr"/>/li>
    
  2. <FILE Action="Delete" Path="editors/nvi2-port/Makefile"/>
    <FILE Action="Delete" Path="editors/nvi2-port/distinfo"/>
    <FILE Action="Delete" Path="editors/nvi2-port/pkg-descr"/>
    <FILE Action="Add" Path="editors/nvi2/Makefile"/>
    <FILE Action="Add" Path="editors/nvi2/distinfo"/>
    <FILE Action="Add" Path="editors/nvi2/pkg-descr"/>
    

Both sets of XML amount to the same results. I am not yet sure which one I like better.

Logistically, the first option shows what is happening: you can see where A is becoming B.

In option 2, that is not so clear.

I think option 1 is the way I’m going to go. This blog post serves to document the above and to help me when the time comes to alter the code.

Things to code

The code has to cater for the Makefile Rename and for the Makefile Delete. The former happens here in this example. The latter would happen when a port is deleted.

Let’s look at databases/sqliteodbc-sqlite2 which was removed on 27 Jul 2020 18:50:49 with this commit:

  • the email
  • The XML:
                <FILE Action="Remove" Revision="543544" Path="head/databases/sqliteodbc-sqlite2/"></FILE>
                <FILE Path="head/MOVED" Action="Modify" Revision="543544"></FILE>
                <FILE Path="head/databases/Makefile" Revision="543544" Action="Modify"></FILE>
    

Here, we have the directory head/databases/sqliteodbc-sqlite2 being deleted. This SVN works well.

Let’s look at this in terms of the git XML:

<FILE Action="Modify" Path="MOVED"/>
<FILE Action="Modify" Path="databases/Makefile"/>
<FILE Action="Delete" Path="databases/sqliteodbc-sqlite2/Makefile"/>

It seems the Delete under git is the same as Remove under svn.

The git code needs to be modified to recognize that a Makefile is being deleted and when that happens, also delete the element and the port.

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