Where’s the diff?

A few months ago, Dmitry Marakasov asked for a new feature: a link to diff.

The problem I had was figuring out the previous revision. The code always has the current revision. That is stored in the table:

freshports.org=#  \d commit_log_elements
                               Table "public.commit_log_elements"
    Column     |     Type     |                            Modifiers
---------------+--------------+------------------------------------------------------------------
 id            | integer      | not null default nextval('commit_log_elements_id_seq'::regclass)
 commit_log_id | integer      | not null
 element_id    | integer      | not null
 revision_name | text         |
 change_type   | character(1) | not null
Indexes:
    "commit_log_elements_pkey" PRIMARY KEY, btree (id)
    "commit_log_elements_clid" btree (commit_log_id)
    "commit_log_elements_ei" btree (element_id)
Check constraints:
    "commit_log_elements_change_type" CHECK (change_type = 'A'::bpchar OR change_type = 
        'M'::bpchar OR change_type = 'R'::bpchar)
Foreign-key constraints:
    "$1" FOREIGN KEY (commit_log_id) REFERENCES commit_log(id) ON UPDATE CASCADE ON 
         DELETE CASCADE
    "$2" FOREIGN KEY (element_id, revision_name) REFERENCES element_revision(element_id, 
         revision_name) ON UPDATE CASCADE ON DELETE CASCADE
Referenced by:
    TABLE "commit_log_port_elements" CONSTRAINT "$2" FOREIGN KEY (commit_log_element_id) 
         REFERENCES commit_log_elements(id) ON UPDATE CASCADE ON DELETE CASCADE
Triggers:
    element_delete_check BEFORE INSERT OR UPDATE ON commit_log_elements FOR EACH ROW 
         EXECUTE PROCEDURE element_delete_check()

There is it, right there, in revision_name. It contains stuff like this:

freshports.org=# select * from commit_log_elements order by id desc limit 60;
   id    | commit_log_id | element_id | revision_name | change_type
---------+---------------+------------+---------------+-------------
 1534684 |        379870 |     354019 | 1.2           | M
 1534683 |        379870 |     354014 | 1.2           | M
 1534682 |        379869 |     221937 | 1.2           | M
 1534681 |        379869 |     221935 | 1.8           | M
 1534680 |        379868 |     240127 | 1.30          | M
 1534679 |        379867 |     102768 | 1.22          | M
 1534678 |        379866 |     354111 | 1.3           | M
 1534677 |        379865 |     136152 | 1.244         | M
 1534676 |        379865 |     284011 | 1.15          | M
 1534675 |        379865 |     136112 | 1.85          | M
 1534674 |        379865 |     311651 | 1.20          | M
 1534673 |        379865 |     216772 | 1.127         | M
 1534672 |        379864 |     259820 | 1.13          | M
 1534671 |        379864 |     236271 | 1.9           | M
 1534670 |        379864 |     284164 | 1.41          | M
 1534669 |        379864 |     253791 | 1.55          | M
 1534668 |        379864 |      56333 | 1.93          | M
 1534667 |        379863 |     214941 | 1.6.2.2       | M
 1534666 |        379862 |     214941 | 1.8.2.2       | M
 1534665 |        379861 |     304100 | 1.92          | M
 1534664 |        379860 |     219241 | 1.1.10.4      | M
 1534663 |        379859 |     234097 | 1.2.2.1       | M
 1534662 |        379859 |     226441 | 1.5.2.1       | M
 1534661 |        379859 |     226438 | 1.5.2.1       | M
 1534660 |        379859 |     297415 | 1.3.2.2       | A
 1534659 |        379859 |     294597 | 1.2.4.2       | A
 1534658 |        379859 |     294596 | 1.7.2.2       | A
 1534657 |        379859 |     295929 | 1.5.2.2       | A
 1534656 |        379859 |     295928 | 1.3.2.2       | A
 1534655 |        379859 |     339174 | 1.1.4.2       | A
 1534654 |        379859 |     339173 | 1.1.4.2       | A
 1534653 |        379859 |     339172 | 1.1.4.2       | A

Over in svn.freshports.org, we have similar:

svn.freshports.org=# select * from commit_log_elements order by id desc limit 30;
   id    | commit_log_id | element_id | revision_name | change_type
---------+---------------+------------+---------------+-------------
 1755850 |        402089 |     457016 | 1.21          | M
 1755849 |        402088 |     456648 | 1.2           | M
 1755848 |        402088 |     456643 | 1.2           | M
 1755847 |        402087 |     221937 | 1.2           | M
 1755846 |        402087 |     221935 | 1.8           | M
 1755845 |        402086 |     240127 | 1.30          | M
 1755844 |        402085 |     102768 | 1.22          | M
 1755843 |        402084 |     456871 | 1.3           | M
 1755842 |        402083 |     136152 | 1.244         | M
 1755841 |        402083 |     284011 | 1.15          | M
 1755840 |        402083 |     136112 | 1.85          | M
 1755839 |        402083 |     311555 | 1.20          | M
 1755838 |        402083 |     216772 | 1.127         | M
 1755837 |        402082 |     259820 | 1.13          | M
 1755836 |        402082 |     236271 | 1.9           | M
 1755835 |        402082 |     284164 | 1.41          | M
 1755834 |        402082 |     253791 | 1.55          | M
 1755833 |        402082 |      56333 | 1.93          | M
 1755832 |        402081 |     214941 | 1.6.2.2       | M
 1755831 |        402080 |     453211 | 213754        | M
 1755830 |        402080 |     412765 | 213754        | M
 1755829 |        402080 |     311620 | 213754        | M
 1755828 |        402079 |     214941 | 1.8.2.2       | M
 1755827 |        402078 |     453211 | 213753        | M
 1755826 |        402078 |     412765 | 213753        | M
 1755825 |        402078 |     311620 | 213753        | M
 1755824 |        402077 |     304100 | 1.92          | M
 1755823 |        402076 |     313721 | 213752        | M
 1755822 |        402075 |     219241 | 1.1.10.4      | M
 1755821 |        402074 |     317668 | 213751        | M
(30 rows)

svn.freshports.org=#

Thus, we must cater for both svn and cvs. FreshPorts records data for all FreeBSD commits, not just the ports tree; it also covers the source tree, which is in svn.

Here is the PHP code I came up with:

function GetPreviousRevision( $revision ) {
  // if we find a dot, decrement the bit after the last dot
  // hence, a cvs revision
  // if no dot, treat it as an svn revision

  $dotPos = strrpos( $revision, '.' );

  if ( $dotPos === false ) {
    $prev = intval ( $revision ) - 1;
  } else {
    $beforeLastDot = substr( $revision, 0, $dotPos + 1 );

    $afterDot = substr( $revision, $dotPos + 1 );
    if ( $afterDot === false ) {
      syslog( LOG_ERR, 'decimal not found in ' . $revision);
      $prev = $revision;
    } else {
      // previous revision is before dot || (after dot - 1)
      $prev = $beforeLastDot . ( intval( $afterDot ) - 1 );
    }
  }


  return $prev;
}

The output is available on the beta website and will soon move to the production site..

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

Leave a Comment

Scroll to Top