[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Build Dependencies with OR



Jason Gunthorpe wrote:

On Wed, 15 Jan 2003, Asier Llano Palacios wrote:

If I understand the source code properly (maybe I am wrong) when we call:

apt-get build-dep whatever

It ignores the OR Build-Dependencies.
It treats these dependencies as being the same:

Build-Depends: a, b | c, d

and

Build-Depends: a, b, c, d

Might do, are you looking at CVS or the released source? I know some
fixing was done after the fact.

I don't think anyone else is trying to fix this.

Jason

Hi,

I've fixed it.
I atach you the result of a 'cvs diff'
(If you prefer any other format for the patch, just tell me)
I've tested it with a lot of packages and I think it works properly.

It now does the following:

foreach comma separated dependencies
{
   foreach | separated dependencies
   {
       check if it is unknown
       check if it should be installed (build dependency)
       check if it should be removed (build conflict)
   }

   if one of the dependencies is not already installed
   {
       if there is just one to install
           schedule it to install
       elseif there is no one to install and just on to remove
           schedule it to remove
       else
       {
           show the information to the user to let him/her decide
           which one to install or to remove.
           (this is the unusual case, because when there are several
           dependencies with OR are usually to let a package
           be in woody/sarge/sid/hurd and it usually only have
           a package to install, and the others are unknown)
           exit
       }
   }
}

install/remove every scheduled file

If you find this behaviour right, you could use the patch I've attached.
If you think this behaviour could be improved, just tell me (or do it yourself, whatever you prefer).

I think it changes the following bugs to pending:

#98640, #126938, #131265 , #145997
(I don't know if any other bug is fixed, because I haven't read all of them).

Cheers,
Asier Llano


? builddep.cvsdiff
Index: cmdline/apt-get.cc
===================================================================
RCS file: /cvs/deity/apt/cmdline/apt-get.cc,v
retrieving revision 1.123
diff -r1.123 apt-get.cc
1919a1920,1922
>       vector <string> notfound;
>       vector <pkgCache::PkgIterator> toinstall;
>       vector <pkgCache::PkgIterator> toremove;
1921c1924,1926
<       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
---
> 
>       /* Foreach comma separated dependencies: AND */
>       for (D = BuildDeps.begin(); D != BuildDeps.end(); )
1923,1924c1928,1933
< 	 pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
< 	 if (Pkg.end() == true)
---
>          vector < pkgSrcRecords::Parser::BuildDepRec >::iterator startor = D;
>          bool lastor = true;
>          bool doneor = false;
>          
>          /* Foreach | separated dependencies: OR */
>          for(; D != BuildDeps.end(  ) && lastor; D++ )
1926c1935,1960
< 	    /* for a build-conflict; ignore unknown packages */
---
>             /* Update if the element is inside an OR operation */
>             lastor = ((*D).Op & pkgCache::Dep::Or) != 0;
>             /* If the or depencies are already met, then we just skip every or element */
>             if( doneor )
>                continue;
> 
>             /* Get the package of the build dependency */
>             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
> 
>             /* Check if the package is an unknown one */
>             if (Pkg.end() == true)
>             {
>   	       /* for a build-conflict; ignore unknown packages */
> 	       if ((*D).Type == pkgSrcRecords::Parser::BuildConflict || 
> 	           (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
> 		   continue;
> 
>                /* Add the package to the vector of not found packages */
>                notfound.push_back( ( *D ).Package );
>                continue;
>             }
> 
>             /* Get the installed version */
> 	    pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
> 	 
>             /* If the dependency is a build conflict schedule it to be removed */
1929c1963,1971
< 		continue;
---
> 	    {
> 	       /* conflict; need to remove if we have an installed version 
> 	        * that satisfies the version criterial */
> 	       if (IV.end() == false && 
>   		   Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
>                   toremove.push_back( Pkg );
>                else
>                   doneor = true;
> 	    } 
1931,1934c1973,2006
< 	    return _error->Error(_("%s dependency on %s cannot be satisfied because the package %s cannot be found"),
< 				 Last->BuildDepType((*D).Type),Src.c_str(),(*D).Package.c_str());
<          }
< 	 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
---
>             /* If the dependency is a build dependency check if it is installed
>              * or schedule it to be installed */
> 	    else 
> 	    {
> 	       /* If this is a virtual package, we need to check the list of
> 	        * packages that provide it and see if any of those are
> 	        * installed */
>                pkgCache::PrvIterator Prv = Pkg.ProvidesList();
>                for (; Prv.end() != true; Prv++)
> 	          if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
> 	             break;
> 
>                /* If it was not found */
> 	       if (Prv.end() == true)
> 	       {
> 	          /* depends; need to install or upgrade if we don't have the
> 	           * package installed or if the version does not satisfy the
> 	           * build dep. This is complicated by the fact that if we
> 	           * depend on a version lower than what we already have 
> 	           * installed it is not clear what should be done; in practice
> 	           * this case should be rare though and right now nothing
> 	           * is done about it :-( */
> 	          if (IV.end() == true ||
> 	             Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
> 	                toinstall.push_back( Pkg );
>                   else
>                      doneor = true;
> 	       }
>                
>                /* If the dependencies are properly installed */
>                else
>                   doneor = true;
>             }
> 	 }
1936,1957c2008,2013
< 	 if ((*D).Type == pkgSrcRecords::Parser::BuildConflict || 
< 	     (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
< 	 {
< 	    /* 
< 	     * conflict; need to remove if we have an installed version 
< 	     * that satisfies the version criterial 
< 	     */
< 	    if (IV.end() == false && 
< 		Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
< 	       TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
< 	 } 
< 	 else 
< 	 {
< 	    /* 
< 	     * If this is a virtual package, we need to check the list of
< 	     * packages that provide it and see if any of those are
< 	     * installed
< 	     */
<             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
<             for (; Prv.end() != true; Prv++)
< 	       if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
< 	          break;
---
>          // If the or group was not fit
>          if( ! doneor )
>          {
>             // If there is just one package to install ...
>             if( toinstall.size() == 1 )
>                TryToInstall( *toinstall.begin(), Cache, Fix, false, false, ExpectedInst );
1959,1974c2015,2053
< 	    if (Prv.end() == true)
< 	    {
< 	       /* 
< 		* depends; need to install or upgrade if we don't have the
< 	        * package installed or if the version does not satisfy the
< 	        * build dep. This is complicated by the fact that if we
< 	        * depend on a version lower than what we already have 
< 	        * installed it is not clear what should be done; in practice
< 	        * this case should be rare though and right now nothing
< 	        * is done about it :-( 
< 		*/
< 	       if (IV.end() == true ||
< 	          Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
< 	             TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst);
< 	    }
< 	 }	       
---
>             // If there is no pacakge to install and one to remove
>             else if( toinstall.size() == 0 && toremove.size() == 1 )
>                TryToInstall( *toremove.begin(), Cache, Fix, true, false, ExpectedInst );
> 
>             // If there is more than one package to install show them to the user
>             else
>             {
>                if( toinstall.size() > 0 )
>                {
>                   string List;
>                   for( unsigned showindex=0; showindex<toinstall.size(); showindex++ )
>                      List += string( toinstall[showindex].Name() ) + " ";
>                   ShowList( c1out, _( "One of the following packages should be installed:\n"), List );
>                }
>                if( toremove.size() > 0 )
>                {
>                   string List;
>                   for( unsigned showindex=0; showindex<toremove.size(); showindex++ )
>                      List += string( toremove[showindex].Name() ) + " ";
>                   if( toinstall.size() > 0 )
>                      ShowList( c1out, _( "or one of the following packages should be removed:\n"), List );
>                   else
>                      ShowList( c1out, _( "One of the following packages should be removed:\n"), List );
>                }
>                if( notfound.size() > 0 )
>                {
>                   string List;
>                   for( unsigned showindex=0; showindex<notfound.size(); showindex++ )
>                      List += notfound[showindex] + " ";
>                   ShowList( c1out, _( "No one of the following packages was found:\n"), List );
>                }
>                return _error->Error( _( "The building dependencies cannot be automatically filled,\nso the user should fix them by hand and retry the build-dep command\n" ) );
>             }
>          }
>          
>          /* Clear the OR data */
>          notfound.clear();
>          toinstall.clear();
>          toremove.clear();

Reply to: