2011-01-10 13:02:49 +03:00
/*
* interdep . c - inter - package analysis and optimizations based on
2018-12-20 04:36:24 +03:00
* strict dependencies between subpackages ( Requires : N = [ E : ] V - R [ : D ] ) .
2011-01-10 13:02:49 +03:00
*
* Written by Alexey Tourbin < at @ altlinux . org > .
* License : GPLv2 + .
*/
# include "system.h"
2011-01-14 07:06:46 +03:00
# include "psm.h" // TFI_t
2011-01-10 13:02:49 +03:00
# include "rpmbuild.h"
# include "interdep.h"
2011-01-14 07:06:46 +03:00
static
const char * pkgName ( Package pkg )
{
TFI_t fi = pkg - > cpioList ;
if ( fi )
return fi - > name ;
const char * name ;
2019-02-25 05:06:13 +03:00
headerName ( pkg - > header , & name ) ;
2011-01-14 07:06:46 +03:00
return name ;
}
2011-01-10 13:02:49 +03:00
static
const char * skipPrefixDash ( const char * str , const char * prefix )
{
int len = strlen ( prefix ) ;
if ( strncmp ( str , prefix , len ) )
return NULL ;
if ( str [ len ] ! = ' - ' )
return NULL ;
return str + len + 1 ;
}
struct Req {
int c ;
struct Pair {
Package pkg1 ;
Package pkg2 ;
} * v ;
} ;
static
int Requires ( struct Req * r , Package pkg1 , Package pkg2 )
{
int i ;
for ( i = 0 ; i < r - > c ; i + + )
if ( pkg1 = = r - > v [ i ] . pkg1 & & pkg2 = = r - > v [ i ] . pkg2 )
return 1 ;
return 0 ;
}
static
2013-01-25 05:31:40 +04:00
int addRequires ( struct Req * r , Package pkg1 , Package pkg2 )
2011-01-10 13:02:49 +03:00
{
2011-02-03 23:10:49 +03:00
if ( pkg1 = = pkg2 )
2013-01-25 05:31:40 +04:00
return 0 ;
2011-01-10 13:02:49 +03:00
if ( Requires ( r , pkg1 , pkg2 ) )
2013-01-25 05:31:40 +04:00
return 0 ;
2011-01-10 13:02:49 +03:00
AUTO_REALLOC ( r - > v , r - > c , 8 ) ;
r - > v [ r - > c + + ] = ( struct Pair ) { pkg1 , pkg2 } ;
2013-01-25 05:31:40 +04:00
return 1 ;
2011-01-10 13:02:49 +03:00
}
2013-01-25 09:00:10 +04:00
static void
propagateRequires ( struct Req * r )
{
unsigned propagated ;
do {
propagated = 0 ;
int i1 , i2 ;
for ( i1 = 0 ; i1 < r - > c ; i1 + + )
for ( i2 = i1 ; i2 < r - > c ; i2 + + ) {
struct Pair r1 = r - > v [ i1 ] ;
struct Pair r2 = r - > v [ i2 ] ;
if ( r1 . pkg2 = = r2 . pkg1 & & addRequires ( r , r1 . pkg1 , r2 . pkg2 ) )
propagated = 1 ;
if ( r2 . pkg2 = = r1 . pkg1 & & addRequires ( r , r2 . pkg1 , r1 . pkg2 ) )
propagated = 1 ;
}
}
while ( propagated ) ;
}
static void
addDeps1 ( struct Req * r , Package pkg1 , Package pkg2 )
{
const char * name = pkgName ( pkg2 ) ;
2018-12-20 04:36:24 +03:00
const char * evrd = headerSprintf ( pkg2 - > header ,
" %|epoch?{%{epoch}:}|%{version}-%{release}%|disttag?{:%{disttag}}| " ,
2013-01-25 09:00:10 +04:00
rpmTagTable , rpmHeaderFormats , NULL ) ;
2018-12-20 04:36:24 +03:00
assert ( evrd ) ;
2013-01-25 09:00:10 +04:00
int flags = RPMSENSE_EQUAL | RPMSENSE_FIND_REQUIRES ;
2018-12-20 04:36:24 +03:00
int added = ! addReqProv ( NULL , pkg1 - > header , flags , name , evrd , 0 ) ;
2013-01-25 09:00:10 +04:00
if ( added ) {
build/interdep.c: always fix interpackage deps that need Epoch or Disttag
This completes the intention of de77ec455683b9c1d650c9e1f60daaa6567951f3
"build/interdep.c: fix interpackage dependencies automatically":
> ...This change also downgrades "dependency needs Epoch" error to warning
> because it automatically adds strict dependencies.
However, the dependency pkg1->pkg2 was not fixed (if it needed an epoch
or disttag) if pkg1 was already considered to have a strict transitive
dependency on pkg2 (perhaps, via another pkg3: if pkg1->pkg3 and
pkg3->pkg2 deps have already been fixed and added as strict ones).
Then, if pkg3 was a part of a cycle, the pkg1->pkg2 dep wasn't
optimized out. So, it was left untouched, not in the nice format of a
strict dep (i.e., missing an epoch or a disttag).
This was not dangerous, because the strictness was guaranteed by the
transitive dependency, but it was not nice, and was inconvenient for
tools which happen to compare the dep versions as whole strings (say,
for rpm and apt optimizations, or for disttag-unaware old rpm or apt).
2019-02-25 03:41:04 +03:00
if ( addRequires ( r , pkg1 , pkg2 ) )
propagateRequires ( r ) ;
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL , " Adding to %s a strict dependency on %s \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2013-01-25 09:00:10 +04:00
}
2018-12-20 04:36:24 +03:00
evrd = _free ( evrd ) ;
2013-01-25 09:00:10 +04:00
}
2011-01-10 13:02:49 +03:00
static
2013-01-25 09:00:10 +04:00
void makeReq1 ( struct Req * r , Package pkg1 , Package pkg2 , int warn )
2011-01-10 13:02:49 +03:00
{
int c = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
int ok =
hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & c ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv , NULL ) ;
if ( ! ok )
return ;
2018-12-20 04:36:24 +03:00
const char * provN , * provV , * provR , * provD ;
headerNVRD ( pkg2 - > header , & provN , & provV , & provR , & provD ) ;
2011-01-10 13:02:49 +03:00
int i ;
for ( i = 0 ; i < c ; i + + ) {
if ( strcmp ( reqNv [ i ] , provN ) )
continue ;
if ( ( reqFv [ i ] & RPMSENSE_SENSEMASK ) ! = RPMSENSE_EQUAL )
continue ;
const char * reqVR = reqVv [ i ] ;
if ( * reqVR = = ' \0 ' )
continue ;
2011-02-08 05:21:38 +03:00
const char * colon = NULL ;
2011-01-10 13:02:49 +03:00
const char * reqR = skipPrefixDash ( reqVR , provV ) ;
2011-02-08 05:21:38 +03:00
if ( reqR = = NULL & & xisdigit ( * reqVR ) ) {
colon = strchr ( reqVR , ' : ' ) ;
2018-12-20 04:36:24 +03:00
if ( colon ) {
/* reqVR contains an epoch */
2011-01-10 13:02:49 +03:00
reqR = skipPrefixDash ( colon + 1 , provV ) ;
2018-12-20 04:36:24 +03:00
}
2011-01-10 13:02:49 +03:00
}
if ( reqR = = NULL )
continue ;
2018-12-20 04:36:24 +03:00
const char * reqD = NULL ;
if ( strcmp ( reqR , provR ) ) {
/* Check whether reqR contains a disttag. */
reqD = strchr ( reqR , ' : ' ) ;
if ( ! reqD )
continue ;
if ( strncmp ( provR , reqR , reqD - reqR )
| | provR [ reqD - reqR ] )
continue ;
reqD + + ;
if ( provD & & strcmp ( provD , reqD ) )
continue ;
}
2013-01-24 11:04:14 +04:00
if ( warn & & colon = = NULL & & headerIsEntry ( pkg2 - > header , RPMTAG_EPOCH ) ) {
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_WARNING , " %s: dependency on %s needs Epoch \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2013-01-25 09:00:10 +04:00
addDeps1 ( r , pkg1 , pkg2 ) ;
2018-12-20 04:36:24 +03:00
} else if ( warn & & provD & & ! reqD ) {
rpmMessage ( RPMMESS_DEBUG , " %s: dependency on %s needs disttag \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
addDeps1 ( r , pkg1 , pkg2 ) ;
2013-01-25 09:00:10 +04:00
} else {
addRequires ( r , pkg1 , pkg2 ) ;
2013-01-24 11:04:14 +04:00
}
2011-01-10 13:02:49 +03:00
break ;
}
const HFD_t hfd = ( HFD_t ) headerFreeData ;
reqNv = hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
}
2011-02-08 06:57:03 +03:00
# include "al.h"
// check if pkg1 has (possibly non-strict) dependency on pkg2
static
int depRequires ( Package pkg1 , Package pkg2 )
{
2013-01-25 09:00:10 +04:00
if ( pkg1 = = pkg2 )
return 0 ;
2011-02-08 06:57:03 +03:00
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
int ok =
hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv , NULL ) ;
if ( ! ok )
return 0 ;
2013-01-25 09:00:10 +04:00
struct availableList_s proval ;
alCreate ( & proval ) ;
alAddPackage ( & proval , pkg2 - > header , NULL , NULL , NULL ) ;
2011-02-08 06:57:03 +03:00
int i ;
struct availablePackage * ap = NULL ;
for ( i = 0 ; i < reqc ; i + + ) {
2013-01-25 09:00:10 +04:00
ap = alSatisfiesDepend ( & proval , reqNv [ i ] , reqVv [ i ] , reqFv [ i ] ) ;
2011-02-08 06:57:03 +03:00
if ( ap )
break ;
}
const HFD_t hfd = ( HFD_t ) headerFreeData ;
reqNv = hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
2013-01-25 09:00:10 +04:00
alFree ( & proval ) ;
2011-02-08 06:57:03 +03:00
return ap ? 1 : 0 ;
}
2013-01-25 09:00:10 +04:00
static
struct Req * freeRequires ( struct Req * r )
2013-01-24 06:42:31 +04:00
{
2013-01-25 09:00:10 +04:00
r - > v = _free ( r - > v ) ;
return _free ( r ) ;
2013-01-24 06:42:31 +04:00
}
2013-01-25 09:00:10 +04:00
/*
* For every subpackage pkg2 in the set , pkg1 will get a strict dep
2013-01-27 00:09:15 +04:00
* on pkg2 if at least one of these conditions is met :
* - pkg1 has a RPMSENSE_FIND_REQUIRES dep on pkg2 ;
* - pkg1 has a manual dep on pkg2 and
* this dep has no ~ RPMSENSE_EQUAL sense flags ;
2013-01-25 09:00:10 +04:00
* - pkg1 has a RPMSENSE_FIND_REQUIRES dep on X , and
2013-01-27 00:09:15 +04:00
* pkg2 is the only subpackage in the set that satisfies X .
2013-01-25 09:00:10 +04:00
*/
2013-01-24 06:42:31 +04:00
static void
2013-01-25 09:00:10 +04:00
fix_weak_deps ( struct Req * r , Package pkg1 , Package packages )
2013-01-24 06:42:31 +04:00
{
2013-01-25 09:00:10 +04:00
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
int ok =
hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv , NULL ) ;
if ( ! ok )
return ;
int i ;
Package pkg2 ;
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next )
; ;
Package * provs = xcalloc ( i , sizeof ( * provs ) ) ;
availableList proval = xcalloc ( i , sizeof ( * proval ) ) ;
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList ) {
2013-01-25 09:00:10 +04:00
alCreate ( & proval [ i ] ) ;
alAddPackage ( & proval [ i ] , pkg2 - > header , NULL , NULL , NULL ) ;
}
}
for ( i = 0 ; i < reqc ; + + i ) {
2013-01-27 00:09:15 +04:00
if ( reqFv [ i ] & RPMSENSE_SENSEMASK & ~ RPMSENSE_EQUAL & &
! ( reqFv [ i ] & RPMSENSE_FIND_REQUIRES ) )
continue ;
int j ;
for ( j = 0 , pkg2 = packages ; pkg2 ; + + j , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList & & ! strcmp ( reqNv [ i ] , pkgName ( pkg2 ) ) ) {
2013-01-27 00:09:15 +04:00
provs [ j ] = pkg2 ;
break ;
}
}
int k ;
2013-01-25 09:00:10 +04:00
Package prov = NULL ;
for ( j = 0 , pkg2 = packages ; pkg2 ; + + j , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList ) {
2013-01-25 09:00:10 +04:00
if ( alSatisfiesDepend ( & proval [ j ] , reqNv [ i ] , reqVv [ i ] , reqFv [ i ] ) ) {
if ( prov ) {
prov = NULL ;
break ;
}
prov = pkg2 ;
k = j ;
}
}
}
2013-01-27 00:09:15 +04:00
if ( prov & & reqFv [ i ] & RPMSENSE_FIND_REQUIRES )
provs [ k ] = prov ;
2013-01-25 09:00:10 +04:00
}
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList )
2013-01-25 09:00:10 +04:00
alFree ( & proval [ i ] ) ;
}
proval = _free ( proval ) ;
const HFD_t hfd = ( HFD_t ) headerFreeData ;
reqNv = hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next ) {
if ( provs [ i ] )
addDeps1 ( r , pkg1 , provs [ i ] ) ;
}
provs = _free ( provs ) ;
2013-01-24 06:42:31 +04:00
}
2011-01-10 13:02:49 +03:00
static
2013-01-25 09:00:10 +04:00
struct Req * makeRequires ( Spec spec , int warn )
2011-01-10 13:02:49 +03:00
{
2013-01-24 06:42:31 +04:00
struct Req * r = xcalloc ( 1 , sizeof * r ) ;
2011-01-10 13:02:49 +03:00
Package pkg1 , pkg2 ;
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
2011-01-10 13:02:49 +03:00
for ( pkg2 = pkg1 - > next ; pkg2 ; pkg2 = pkg2 - > next ) {
2013-01-28 21:49:48 +04:00
if ( ! pkg2 - > cpioList )
continue ;
2013-01-25 09:00:10 +04:00
makeReq1 ( r , pkg1 , pkg2 , warn & 1 ) ;
makeReq1 ( r , pkg2 , pkg1 , warn & 1 ) ;
2011-01-10 13:02:49 +03:00
}
2013-01-28 21:49:48 +04:00
}
2013-01-25 09:00:10 +04:00
propagateRequires ( r ) ;
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
2013-01-25 09:00:10 +04:00
fix_weak_deps ( r , pkg1 , spec - > packages ) ;
2013-01-28 21:49:48 +04:00
}
2011-02-08 06:57:03 +03:00
if ( ( warn & 2 ) = = 0 )
return r ;
2013-01-24 06:42:31 +04:00
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
2011-02-08 06:57:03 +03:00
for ( pkg2 = pkg1 - > next ; pkg2 ; pkg2 = pkg2 - > next ) {
2013-01-28 21:49:48 +04:00
if ( ! pkg2 - > cpioList )
continue ;
2011-02-08 06:57:03 +03:00
if ( ! Requires ( r , pkg1 , pkg2 ) & & depRequires ( pkg1 , pkg2 ) )
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_WARNING , " %s: non-strict dependency on %s \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2011-02-08 06:57:03 +03:00
if ( ! Requires ( r , pkg2 , pkg1 ) & & depRequires ( pkg2 , pkg1 ) )
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_WARNING , " %s: non-strict dependency on %s \n " ,
pkgName ( pkg2 ) , pkgName ( pkg1 ) ) ;
2011-02-08 06:57:03 +03:00
}
2013-01-28 21:49:48 +04:00
}
2011-01-10 13:02:49 +03:00
return r ;
}
2011-01-14 07:10:39 +03:00
# include "checkFiles.h" // fiIntersect
static
void fiPrune ( TFI_t fi , char pruned [ ] )
{
2011-01-12 15:00:25 +03:00
int * dil_ ;
const char * * bnl , * * dnl ;
int bnc , dnc , dic ;
int ok =
fi - > hge ( fi - > h , RPMTAG_BASENAMES , NULL , ( void * * ) & bnl , & bnc ) & &
fi - > hge ( fi - > h , RPMTAG_DIRNAMES , NULL , ( void * * ) & dnl , & dnc ) & &
fi - > hge ( fi - > h , RPMTAG_DIRINDEXES , NULL , ( void * * ) & dil_ , & dic ) ;
assert ( ok ) ;
assert ( fi - > fc = = bnc ) ;
assert ( bnc = = dic ) ;
2011-01-13 10:57:30 +03:00
int i , j , k ;
2011-01-12 15:00:25 +03:00
// dil must be copied, cf. relocateFileList
int dil [ dic ] ;
for ( i = 0 ; i < dic ; i + + )
dil [ i ] = dil_ [ i ] ;
// mark used dirnames
int dirused [ dnc ] ;
bzero ( dirused , dnc * sizeof * dirused ) ;
for ( i = 0 ; i < bnc ; i + + )
if ( ! pruned [ i ] )
dirused [ dil [ i ] ] + + ;
int propagated ;
do {
propagated = 0 ;
// for each unused dirname
for ( i = 0 ; i < dnc ; i + + ) {
if ( dirused [ i ] )
continue ;
// find its corresponding parent_dir+name entry
for ( j = 0 ; j < bnc ; j + + ) {
if ( pruned [ j ] )
continue ;
const char * D = dnl [ i ] ;
const char * d = dnl [ dil [ j ] ] ;
int dlen = strlen ( d ) ;
if ( strncmp ( D , d , dlen ) )
continue ;
const char * b = bnl [ j ] ;
int blen = strlen ( b ) ;
if ( strncmp ( D + dlen , b , blen ) )
continue ;
if ( strncmp ( D + dlen + blen , " / " , 2 ) )
continue ;
// makr parent_dir+name for removal
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL , " also prunning dir %s%s \n " , d , b ) ;
2011-01-12 15:00:25 +03:00
pruned [ j ] = 1 ;
// decrement parent_dir usage
if ( - - dirused [ dil [ j ] ] = = 0 )
propagated + + ;
}
}
}
while ( propagated ) ;
2011-01-13 10:57:30 +03:00
// new count for bnc-like values
int oldc = bnc ;
int newc = 0 ;
for ( i = 0 ; i < oldc ; i + + )
if ( ! pruned [ i ] )
newc + + ;
// establish new dirnames and dirindexes
for ( i = 0 , j = 0 ; i < dnc ; i + + ) {
if ( ! dirused [ i ] )
continue ;
if ( i = = j )
goto skip ;
dnl [ j ] = dnl [ i ] ;
for ( k = 0 ; k < dic ; k + + )
if ( dil [ k ] = = i )
dil [ k ] = j ;
skip :
j + + ;
}
dnc = j ;
// handle bnl, dnl and dil
# define PruneV(v) \
for ( i = 0 , j = 0 ; i < oldc ; i + + ) \
if ( ! pruned [ i ] ) \
v [ j + + ] = v [ i ]
PruneV ( bnl ) ;
PruneV ( dil ) ;
PruneV ( fi - > bnl ) ;
PruneV ( fi - > dil ) ;
fi - > hme ( fi - > h , RPMTAG_BASENAMES , RPM_STRING_ARRAY_TYPE , bnl , newc ) ;
fi - > hme ( fi - > h , RPMTAG_DIRNAMES , RPM_STRING_ARRAY_TYPE , dnl , dnc ) ;
fi - > hme ( fi - > h , RPMTAG_DIRINDEXES , RPM_INT32_TYPE , dil , newc ) ;
bnl = fi - > hfd ( bnl , RPM_STRING_ARRAY_TYPE ) ;
dnl = fi - > hfd ( dnl , RPM_STRING_ARRAY_TYPE ) ;
// prune header tags
rpmTagType tagt ;
int tagc ;
const char * * strv ;
# define PruneStrTag(tag) \
if ( fi - > hge ( fi - > h , tag , & tagt , ( void * * ) & strv , & tagc ) ) { \
assert ( tagt = = RPM_STRING_ARRAY_TYPE ) ; \
assert ( tagc = = oldc ) ; \
PruneV ( strv ) ; \
fi - > hme ( fi - > h , tag , RPM_STRING_ARRAY_TYPE , strv , newc ) ; \
fi - > hfd ( strv , RPM_STRING_ARRAY_TYPE ) ; \
}
short * INT16p , INT16v [ oldc ] ;
int * INT32p , INT32v [ oldc ] ;
# define PruneIntTag(INT, tag) \
if ( fi - > hge ( fi - > h , tag , & tagt , ( void * * ) & INT # # p , & tagc ) ) { \
assert ( tagt = = RPM_ # # INT # # _TYPE ) ; \
assert ( tagc = = oldc ) ; \
for ( i = 0 ; i < oldc ; i + + ) \
INT # # v [ i ] = INT # # p [ i ] ; \
PruneV ( INT # # v ) ; \
fi - > hme ( fi - > h , tag , RPM_ # # INT # # _TYPE , INT # # v , newc ) ; \
}
# define PruneI16Tag(tag) PruneIntTag(INT16, tag)
# define PruneI32Tag(tag) PruneIntTag(INT32, tag)
PruneI32Tag ( RPMTAG_FILESIZES ) ;
PruneStrTag ( RPMTAG_FILEUSERNAME ) ;
PruneStrTag ( RPMTAG_FILEGROUPNAME ) ;
PruneI32Tag ( RPMTAG_FILEMTIMES ) ;
PruneI16Tag ( RPMTAG_FILEMODES ) ;
PruneI16Tag ( RPMTAG_FILERDEVS ) ;
PruneI32Tag ( RPMTAG_FILEDEVICES ) ;
PruneI32Tag ( RPMTAG_FILEINODES ) ;
PruneStrTag ( RPMTAG_FILELANGS ) ;
PruneStrTag ( RPMTAG_FILEMD5S ) ;
PruneStrTag ( RPMTAG_FILELINKTOS ) ;
PruneI32Tag ( RPMTAG_FILEVERIFYFLAGS ) ;
PruneI32Tag ( RPMTAG_FILEFLAGS ) ;
// update fi, cf. genCpioListAndHeader
PruneV ( fi - > apath ) ;
PruneV ( fi - > actions ) ;
PruneV ( fi - > fmapflags ) ;
PruneV ( fi - > fuids ) ;
PruneV ( fi - > fgids ) ;
2011-02-05 03:29:28 +03:00
PruneV ( fi - > fsts ) ;
2011-01-13 10:57:30 +03:00
struct transactionFileInfo_s save_fi ;
# define MV(a) save_fi.a = fi->a; fi->a = NULL
MV ( bnl ) ; MV ( dnl ) ; MV ( dil ) ;
2011-02-05 03:29:28 +03:00
MV ( apath ) ; MV ( actions ) ; MV ( fmapflags ) ; MV ( fuids ) ; MV ( fgids ) ; MV ( fsts ) ;
2011-01-13 10:57:30 +03:00
save_fi . h = fi - > h ;
save_fi . astriplen = fi - > astriplen ;
freeFi ( fi ) ;
bzero ( fi , sizeof * fi ) ;
fi - > type = TR_ADDED ;
loadFi ( save_fi . h , fi ) ;
assert ( fi - > fc = = newc ) ;
fi - > dnl = _free ( fi - > dnl ) ;
fi - > bnl = _free ( fi - > bnl ) ;
# undef MV
# define MV(a) fi->a = save_fi.a
MV ( bnl ) ; MV ( dnl ) ; MV ( dil ) ;
2011-02-05 03:29:28 +03:00
MV ( apath ) ; MV ( actions ) ; MV ( fmapflags ) ; MV ( fuids ) ; MV ( fgids ) ; MV ( fsts ) ;
2011-01-13 10:57:30 +03:00
fi - > astriplen = save_fi . astriplen ;
2011-01-14 07:10:39 +03:00
}
2011-01-14 07:06:46 +03:00
static
2015-01-28 19:52:29 +03:00
void fiIntersect_cb ( const TFI_t fi1 , const TFI_t fi2 , const char * f ,
int i1 , int i2 , void * data )
2011-01-14 07:06:46 +03:00
{
2015-01-28 19:52:29 +03:00
( void ) fi2 ;
2011-01-14 07:10:39 +03:00
( void ) i2 ;
2011-01-12 15:00:25 +03:00
if ( S_ISDIR ( fi1 - > fmodes [ i1 ] ) )
return ;
2011-01-14 07:10:39 +03:00
const char src [ ] = " /usr/src/debug/ " ;
if ( strncmp ( f , src , sizeof ( src ) - 1 ) )
return ;
2015-01-28 19:52:29 +03:00
struct {
unsigned int n ;
char list [ fi1 - > fc ] ;
} * pruned = data ;
pruned - > list [ i1 ] = 1 ;
pruned - > n + + ;
2011-01-14 07:10:39 +03:00
}
2015-01-28 19:52:29 +03:00
// prune src dups from pkg1 and add dependency on pkg2
static
void pruneSrc1 ( struct Req * r , Package pkg1 , Package pkg2 )
{
TFI_t fi1 = pkg1 - > cpioList ;
const TFI_t fi2 = pkg2 - > cpioList ;
if ( ! fi1 | | ! fi2 ) return ;
struct {
unsigned int n ;
char list [ fi1 - > fc ] ;
} pruned ;
bzero ( & pruned , sizeof ( pruned ) ) ;
fiIntersect ( fi1 , fi2 , fiIntersect_cb , & pruned ) ;
if ( pruned . n = = 0 )
2011-01-14 07:10:39 +03:00
return ;
2013-01-28 20:22:44 +04:00
addDeps1 ( r , pkg1 , pkg2 ) ;
2013-01-29 02:48:10 +04:00
rpmMessage ( RPMMESS_NORMAL , " Removing from %s %d sources provided by %s \n " ,
2015-01-28 19:52:29 +03:00
pkgName ( pkg1 ) , pruned . n , pkgName ( pkg2 ) ) ;
fiPrune ( fi1 , pruned . list ) ;
2011-01-14 07:06:46 +03:00
}
2011-02-04 02:41:05 +03:00
static void
processDependentDebuginfo ( struct Req * r , Spec spec ,
2013-01-25 09:00:10 +04:00
void ( * cb ) ( struct Req * r , Package pkg1 , Package pkg2 ) , int mutual )
2011-01-14 07:06:46 +03:00
{
int i1 , i2 ;
struct Pair r1 , r2 ;
const char * Nd , * Np ;
const char * suf ;
// r1 = { pkg1-debuginfo, pkg1 }
for ( i1 = 0 ; i1 < r - > c ; i1 + + ) {
r1 = r - > v [ i1 ] ;
Nd = pkgName ( r1 . pkg1 ) ;
Np = pkgName ( r1 . pkg2 ) ;
suf = skipPrefixDash ( Nd , Np ) ;
if ( suf = = NULL | | strcmp ( suf , " debuginfo " ) )
continue ;
// r2 = { pkg2-debuginfo, pkg2 }
for ( i2 = i1 ; i2 < r - > c ; i2 + + ) {
r2 = r - > v [ i2 ] ;
Nd = pkgName ( r2 . pkg1 ) ;
Np = pkgName ( r2 . pkg2 ) ;
suf = skipPrefixDash ( Nd , Np ) ;
if ( suf = = NULL | | strcmp ( suf , " debuginfo " ) )
continue ;
// (pkg1 <-> pkg2) => (pkg1-debuginfo <-> pkg2-debuginfo)
2011-02-04 02:41:05 +03:00
if ( Requires ( r , r1 . pkg2 , r2 . pkg2 ) ) {
2013-01-25 09:00:10 +04:00
cb ( r , r1 . pkg1 , r2 . pkg1 ) ;
2011-02-04 02:41:05 +03:00
if ( ! mutual )
continue ;
}
if ( Requires ( r , r2 . pkg2 , r1 . pkg2 ) )
2013-01-25 09:00:10 +04:00
cb ( r , r2 . pkg1 , r1 . pkg1 ) ;
2011-01-14 07:06:46 +03:00
}
}
}
2011-02-04 02:41:05 +03:00
static
void pruneDebuginfoSrc ( struct Req * r , Spec spec )
{
processDependentDebuginfo ( r , spec , pruneSrc1 , 0 ) ;
}
2011-02-04 05:06:48 +03:00
// if pkg1 implicitly requires pkg2, add strict dependency
2013-01-25 09:00:10 +04:00
static void
liftDeps1 ( struct Req * r , Package pkg1 , Package pkg2 )
2011-02-04 05:06:48 +03:00
{
2013-01-25 09:00:10 +04:00
if ( ! Requires ( r , pkg1 , pkg2 ) & & depRequires ( pkg1 , pkg2 ) )
addDeps1 ( r , pkg1 , pkg2 ) ;
2011-02-04 05:06:48 +03:00
}
static
void liftDebuginfoDeps ( struct Req * r , Spec spec )
{
processDependentDebuginfo ( r , spec , liftDeps1 , 1 ) ;
}
2011-02-06 04:50:32 +03:00
// assuming pkg1 has strict dependency on pkg2, prune deps provided by pkg2
2011-02-04 09:12:08 +03:00
static
void pruneDeps1 ( Package pkg1 , Package pkg2 )
{
TFI_t fi = pkg1 - > cpioList ;
if ( fi = = NULL )
return ;
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv_ = NULL ;
int ok =
fi - > hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
fi - > hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
fi - > hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv_ , NULL ) ;
if ( ! ok )
return ;
assert ( reqc > 0 ) ;
int i , j ;
int reqFv [ reqc ] ;
for ( i = 0 ; i < reqc ; i + + )
reqFv [ i ] = reqFv_ [ i ] ;
2013-01-25 09:00:10 +04:00
struct availableList_s proval ;
alCreate ( & proval ) ;
alAddPackage ( & proval , pkg2 - > header , NULL , NULL , NULL ) ;
2011-02-04 09:12:08 +03:00
int flags = 0 , * flagsp = NULL ;
struct availablePackage * ap = NULL ;
2011-02-05 07:25:46 +03:00
int rpmlibSetVersions = - 1 ;
int hasSetVersions = 0 ;
2011-02-04 09:12:08 +03:00
int npruned = 0 ;
char pruned [ reqc ] ;
bzero ( pruned , reqc ) ;
for ( i = 0 ; i < reqc ; i + + ) {
if ( ( reqFv [ i ] & RPMSENSE_SENSEMASK ) = = RPMSENSE_EQUAL & &
strcmp ( reqNv [ i ] , pkgName ( pkg2 ) ) = = 0 )
{
if ( flagsp = = NULL )
flagsp = & reqFv [ i ] ;
continue ;
}
2011-02-05 07:25:46 +03:00
if ( ( reqFv [ i ] & RPMSENSE_RPMLIB ) & &
strcmp ( reqNv [ i ] , " rpmlib(SetVersions) " ) = = 0 )
{
if ( rpmlibSetVersions = = - 1 )
rpmlibSetVersions = i ;
continue ;
}
2013-01-25 09:00:10 +04:00
ap = alSatisfiesDepend ( & proval , reqNv [ i ] , reqVv [ i ] , reqFv [ i ] ) ;
2011-02-05 07:25:46 +03:00
if ( ap = = NULL ) {
if ( ( reqFv [ i ] & RPMSENSE_SENSEMASK ) )
if ( strncmp ( reqVv [ i ] , " set: " , 4 ) = = 0 )
hasSetVersions + + ;
2011-02-04 09:12:08 +03:00
continue ;
2011-02-05 07:25:46 +03:00
}
2011-02-04 09:12:08 +03:00
pruned [ i ] = 1 ;
npruned + + ;
flags | = reqFv [ i ] ;
}
2013-01-25 09:00:10 +04:00
alFree ( & proval ) ;
2011-02-04 09:12:08 +03:00
if ( npruned = = 0 ) {
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
return ;
}
2011-02-05 07:25:46 +03:00
if ( hasSetVersions = = 0 & & rpmlibSetVersions > = 0 ) {
pruned [ rpmlibSetVersions ] = 1 ;
npruned + + ;
}
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL ,
" Removing %d extra deps from %s due to dependency on %s \n " ,
npruned , pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2011-02-04 09:12:08 +03:00
if ( flagsp )
* flagsp | = ( flags & RPMSENSE_PREREQ ) ;
for ( i = 0 , j = 0 ; i < reqc ; i + + ) {
if ( pruned [ i ] )
continue ;
if ( i = = j )
goto skip ;
reqNv [ j ] = reqNv [ i ] ;
reqVv [ j ] = reqVv [ i ] ;
reqFv [ j ] = reqFv [ i ] ;
skip :
j + + ;
}
reqc = j ;
fi - > hme ( fi - > h , RPMTAG_REQUIRENAME , RPM_STRING_ARRAY_TYPE , reqNv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREVERSION , RPM_STRING_ARRAY_TYPE , reqVv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREFLAGS , RPM_INT32_TYPE , reqFv , reqc ) ;
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
}
static
void pruneExtraDeps ( struct Req * r , Spec spec )
{
int i ;
for ( i = 0 ; i < r - > c ; i + + )
pruneDeps1 ( r - > v [ i ] . pkg1 , r - > v [ i ] . pkg2 ) ;
}
2011-02-06 04:50:32 +03:00
// assuming pkg1 has strict dependency on pkg2, prune deps required by pkg2
static
2011-03-14 05:27:17 +03:00
void pruneRDeps1 ( struct Req * r , Spec spec , Package pkg1 , Package pkg2 )
2011-02-06 04:50:32 +03:00
{
TFI_t fi = pkg1 - > cpioList ;
if ( fi = = NULL )
return ;
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv_ = NULL ;
int ok =
fi - > hge ( fi - > h , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
fi - > hge ( fi - > h , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
fi - > hge ( fi - > h , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv_ , NULL ) ;
if ( ! ok )
return ;
int i , j ;
int reqFv [ reqc ] ;
for ( i = 0 ; i < reqc ; i + + )
reqFv [ i ] = reqFv_ [ i ] ;
int provc = 0 ;
const char * * provNv = NULL ;
const char * * provVv = NULL ;
const int * provFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
const HFD_t hfd = ( HFD_t ) headerFreeData ;
ok =
hge ( pkg2 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & provNv , & provc ) & &
hge ( pkg2 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & provVv , NULL ) & &
hge ( pkg2 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & provFv , NULL ) ;
if ( ! ok ) {
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
return ;
}
int npruned = 0 ;
char pruned [ reqc ] ;
bzero ( pruned , reqc ) ;
2011-03-14 05:27:17 +03:00
// check if pkg2 is part of a cycle
2011-02-07 06:57:43 +03:00
int cycle = 0 ;
Package pkg3 ;
2011-03-14 05:27:17 +03:00
for ( pkg3 = spec - > packages ; pkg3 ; pkg3 = pkg3 - > next ) {
if ( pkg3 = = pkg1 | | pkg3 = = pkg2 )
2011-02-07 06:57:43 +03:00
continue ;
if ( Requires ( r , pkg2 , pkg3 ) & & Requires ( r , pkg3 , pkg2 ) ) {
cycle = 1 ;
break ;
}
}
2011-02-06 04:50:32 +03:00
for ( i = 0 ; i < reqc ; i + + )
2015-01-28 19:52:29 +03:00
for ( j = 0 ; j < provc ; j + + ) {
if ( strcmp ( reqNv [ i ] , provNv [ j ] ) )
continue ;
if ( cycle & & ( reqFv [ i ] & RPMSENSE_SENSEMASK ) = = RPMSENSE_EQUAL )
continue ;
2019-02-27 04:56:24 +03:00
dep_compare_t cmp = compare_deps ( RPMTAG_REQUIREFLAGS ,
2015-01-28 19:52:29 +03:00
provVv [ j ] , provFv [ j ] , reqVv [ i ] , reqFv [ i ] ) ;
if ( ! ( cmp = = DEP_ST | | cmp = = DEP_EQ ) )
continue ;
pruned [ i ] = 1 ;
npruned + + ;
}
2011-02-06 04:50:32 +03:00
if ( npruned = = 0 )
goto free ;
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL ,
" Removing %d extra deps from %s due to repentancy on %s \n " ,
npruned , pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2011-02-06 04:50:32 +03:00
for ( i = 0 , j = 0 ; i < reqc ; i + + ) {
if ( pruned [ i ] )
continue ;
if ( i = = j )
goto skip ;
reqNv [ j ] = reqNv [ i ] ;
reqVv [ j ] = reqVv [ i ] ;
reqFv [ j ] = reqFv [ i ] ;
skip :
j + + ;
}
reqc = j ;
fi - > hme ( fi - > h , RPMTAG_REQUIRENAME , RPM_STRING_ARRAY_TYPE , reqNv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREVERSION , RPM_STRING_ARRAY_TYPE , reqVv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREFLAGS , RPM_INT32_TYPE , reqFv , reqc ) ;
free :
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
provNv = hfd ( provNv , RPM_STRING_ARRAY_TYPE ) ;
provVv = hfd ( provVv , RPM_STRING_ARRAY_TYPE ) ;
}
static
void pruneExtraRDeps ( struct Req * r , Spec spec )
{
Package pkg1 , pkg2 ;
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
for ( pkg2 = pkg1 - > next ; pkg2 ; pkg2 = pkg2 - > next ) {
if ( ! pkg2 - > cpioList )
continue ;
2011-02-06 04:50:32 +03:00
if ( Requires ( r , pkg1 , pkg2 ) )
2011-03-14 05:27:17 +03:00
pruneRDeps1 ( r , spec , pkg1 , pkg2 ) ;
2011-02-06 04:50:32 +03:00
// "else" guards against mutual deletions
else if ( Requires ( r , pkg2 , pkg1 ) )
2011-03-14 05:27:17 +03:00
pruneRDeps1 ( r , spec , pkg2 , pkg1 ) ;
2013-01-28 21:49:48 +04:00
}
}
2011-02-06 04:50:32 +03:00
}
2011-01-10 13:02:49 +03:00
int processInterdep ( Spec spec )
{
2014-11-19 09:31:11 +03:00
struct Req * r ;
int optlevel = rpmExpandNumeric ( " %{?_deps_optimization}%{?!_deps_optimization:3} " ) ;
if ( optlevel > = 1 ) {
r = makeRequires ( spec , 1 ) ;
pruneDebuginfoSrc ( r , spec ) ;
liftDebuginfoDeps ( r , spec ) ;
r = freeRequires ( r ) ;
}
if ( optlevel > = 3 ) {
r = makeRequires ( spec , 2 ) ;
2013-01-24 06:42:31 +04:00
pruneExtraDeps ( r , spec ) ;
pruneExtraRDeps ( r , spec ) ;
2014-11-19 09:31:11 +03:00
r = freeRequires ( r ) ;
2013-01-24 06:42:31 +04:00
}
2011-01-10 13:02:49 +03:00
return 0 ;
}
// ex: set ts=8 sts=4 sw=4 noet: