---

Debian package versioning

It always made me curious how the debian package versinoning works, especially since I saw "odd" sorting behavior during the 20.05 RC1 yesterday, where the 'plain rc1' was considered older than the rc0~750... So with the first commit the output was as follows:
ubuntu@vpp-install:~$ apt-cache policy vpp
vpp:
  Installed: (none)
  Candidate: 20.05-rc1~1-g765ef3767~b3
  Version table:
     20.05-rc1~1-g765ef3767~b3 500
        500 file:/home/ubuntu/repo ./ Packages
     20.05-rc0~750-gb8e900940~b1 500
        500 file:/home/ubuntu/repo ./ Packages
     20.05-rc1~b2 500
        500 file:/home/ubuntu/repo ./ Packages
ubuntu@vpp-install:~$ 
Installing apt-src and subsequent apt-src install apt reveals the secret of how the versions are compared, as per the function in apt-1.6.12ubuntu0.1/apt-pkg/deb/debversion.cc:
/* This fragments the version into E:V-R triples and compares each 
   portion separately. */
int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
                                      const char *B,const char *BEnd)
{
   // Strip off the epoch and compare it
   const char *lhs = (const char*) memchr(A, ':', AEnd - A);
   const char *rhs = (const char*) memchr(B, ':', BEnd - B);
   if (lhs == NULL)
      lhs = A;
   if (rhs == NULL)
      rhs = B;

   // Special case: a zero epoch is the same as no epoch,
   // so remove it.
   if (lhs != A)
   {
      for (; *A == '0'; ++A);
      if (A == lhs)
      {
         ++A;
         ++lhs;
      }
   }
   if (rhs != B)
   {
      for (; *B == '0'; ++B);
      if (B == rhs)
      {
         ++B;
         ++rhs;
      }
   }

   // Compare the epoch
   int Res = CmpFragment(A,lhs,B,rhs);
   if (Res != 0)
      return Res;

   // Skip the :
   if (lhs != A)
      lhs++;
   if (rhs != B)
      rhs++;

   // Find the last -
   const char *dlhs = (const char*) memrchr(lhs, '-', AEnd - lhs);
   const char *drhs = (const char*) memrchr(rhs, '-', BEnd - rhs);
   if (dlhs == NULL)
      dlhs = AEnd;
   if (drhs == NULL)
      drhs = BEnd;

   // Compare the main version
   Res = CmpFragment(lhs,dlhs,rhs,drhs);
   if (Res != 0)
      return Res;

   // Skip the -
   if (dlhs != lhs)
      dlhs++;
   if (drhs != rhs)
      drhs++;

   // no debian revision need to be treated like -0
   if (*(dlhs-1) == '-' && *(drhs-1) == '-')
      return CmpFragment(dlhs,AEnd,drhs,BEnd);
   else if (*(dlhs-1) == '-')
   {
      const char* null = "0";
      return CmpFragment(dlhs,AEnd,null, null+1);
   }
   else if (*(drhs-1) == '-')
   {
      const char* null = "0";
      return CmpFragment(null, null+1, drhs, BEnd);
   }
   else
      return 0;
}

Files in 2020-05-14-Debian-package-versioning:


../
HEADER.txt                                         01-Jul-2024 21:41                2708

(c) Andrew Yourtchenko