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: