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..











