123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- // -*- mode: cpp; mode: fold -*-
- // Description /*{{{*/
- // $Id: debversion.cc,v 1.8 2003/09/10 23:39:49 mdz Exp $
- /* ######################################################################
- Debian Version - Versioning system for Debian
- This implements the standard Debian versioning system.
-
- ##################################################################### */
- /*}}}*/
- // Include Files /*{{{*/
- #include <config.h>
- #include <apt-pkg/debversion.h>
- #include <apt-pkg/pkgcache.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- /*}}}*/
- debVersioningSystem debVS;
- // debVS::debVersioningSystem - Constructor /*{{{*/
- // ---------------------------------------------------------------------
- /* */
- debVersioningSystem::debVersioningSystem()
- {
- Label = "Standard .deb";
- }
- /*}}}*/
- // debVS::CmpFragment - Compare versions /*{{{*/
- // ---------------------------------------------------------------------
- /* This compares a fragment of the version. This is a slightly adapted
- version of what dpkg uses in dpkg/lib/dpkg/version.c.
- In particular, the a | b = NULL check is removed as we check this in the
- caller, we use an explicit end for a | b strings and we check ~ explicit. */
- static int order(char c)
- {
- if (isdigit(c))
- return 0;
- else if (isalpha(c))
- return c;
- else if (c == '~')
- return -1;
- else if (c)
- return c + 256;
- else
- return 0;
- }
- int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
- const char *B,const char *BEnd)
- {
- /* Iterate over the whole string
- What this does is to split the whole string into groups of
- numeric and non numeric portions. For instance:
- a67bhgs89
- Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
- 2.7.2-linux-1
- Has '2', '.', '7', '.' ,'-linux-','1' */
- const char *lhs = A;
- const char *rhs = B;
- while (lhs != AEnd && rhs != BEnd)
- {
- int first_diff = 0;
- while (lhs != AEnd && rhs != BEnd &&
- (!isdigit(*lhs) || !isdigit(*rhs)))
- {
- int vc = order(*lhs);
- int rc = order(*rhs);
- if (vc != rc)
- return vc - rc;
- ++lhs; ++rhs;
- }
- while (*lhs == '0')
- ++lhs;
- while (*rhs == '0')
- ++rhs;
- while (isdigit(*lhs) && isdigit(*rhs))
- {
- if (!first_diff)
- first_diff = *lhs - *rhs;
- ++lhs;
- ++rhs;
- }
- if (isdigit(*lhs))
- return 1;
- if (isdigit(*rhs))
- return -1;
- if (first_diff)
- return first_diff;
- }
- // The strings must be equal
- if (lhs == AEnd && rhs == BEnd)
- return 0;
- // lhs is shorter
- if (lhs == AEnd)
- {
- if (*rhs == '~') return 1;
- return -1;
- }
- // rhs is shorter
- if (rhs == BEnd)
- {
- if (*lhs == '~') return -1;
- return 1;
- }
- // Shouldn't happen
- return 1;
- }
- /*}}}*/
- // debVS::CmpVersion - Comparison for versions /*{{{*/
- // ---------------------------------------------------------------------
- /* 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;
- }
- /*}}}*/
- // debVS::CheckDep - Check a single dependency /*{{{*/
- // ---------------------------------------------------------------------
- /* This simply preforms the version comparison and switch based on
- operator. If DepVer is 0 then we are comparing against a provides
- with no version. */
- bool debVersioningSystem::CheckDep(const char *PkgVer,
- int Op,const char *DepVer)
- {
- if (DepVer == 0 || DepVer[0] == 0)
- return true;
- if (PkgVer == 0 || PkgVer[0] == 0)
- return false;
- Op &= 0x0F;
- // fast track for (equal) strings [by location] which are by definition equal versions
- if (PkgVer == DepVer)
- return Op == pkgCache::Dep::Equals || Op == pkgCache::Dep::LessEq || Op == pkgCache::Dep::GreaterEq;
- // Perform the actual comparison.
- int const Res = CmpVersion(PkgVer, DepVer);
- switch (Op)
- {
- case pkgCache::Dep::LessEq:
- if (Res <= 0)
- return true;
- break;
-
- case pkgCache::Dep::GreaterEq:
- if (Res >= 0)
- return true;
- break;
-
- case pkgCache::Dep::Less:
- if (Res < 0)
- return true;
- break;
-
- case pkgCache::Dep::Greater:
- if (Res > 0)
- return true;
- break;
-
- case pkgCache::Dep::Equals:
- if (Res == 0)
- return true;
- break;
-
- case pkgCache::Dep::NotEquals:
- if (Res != 0)
- return true;
- break;
- }
- return false;
- }
- /*}}}*/
- // debVS::UpstreamVersion - Return the upstream version string /*{{{*/
- // ---------------------------------------------------------------------
- /* This strips all the debian specific information from the version number */
- std::string debVersioningSystem::UpstreamVersion(const char *Ver)
- {
- // Strip off the bit before the first colon
- const char *I = Ver;
- for (; *I != 0 && *I != ':'; I++);
- if (*I == ':')
- Ver = I + 1;
-
- // Chop off the trailing -
- I = Ver;
- unsigned Last = strlen(Ver);
- for (; *I != 0; I++)
- if (*I == '-')
- Last = I - Ver;
-
- return std::string(Ver,Last);
- }
- /*}}}*/
|