From: Keith Marshall Date: Fri, 4 Nov 2011 22:25:10 +0000 (+0000) Subject: Don't upgrade installed DLL components to incompatible version. Provide clearer... X-Git-Tag: r0-6-0-beta-20130904-1~104 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=6fcd46313b21cdb143eb8085ed946507d68be984;p=mingw%2Fmingw-get.git Don't upgrade installed DLL components to incompatible version. Provide clearer diagnostics for failed requests on implied packages. --- diff --git a/ChangeLog b/ChangeLog index 51ef7e5..abecd41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-11-04 Keith Marshall + + Don't upgrade installed DLL components to incompatible version. + Provide clearer diagnostics for failed requests on implied packages. + + * src/pkgdeps.cpp (is_abi_compatible): New static inline function. + (pkgXmlDocument::ResolveDependencies) [is_installed]: Use it. + (pkgXmlDocument::ResolveDependencies) [DEBUG_TRACE_DEPENDENCIES]: + Clean up and improve diagnostic message content and formatting. + (pkgXmlDocument::Schedule) [(upgrade || remove) && ! installed]: + Downgrade diagnostic to WARNING, for implicitly specified component + packages; provide additional explanatory diagnostics. + + * src/pkgspec.cpp (pkgSpecs::VersionComparator): + * src/pkgexec.cpp (pkgActionItem::SelectIfMostRecentFit): + [DEBUG_TRACE_DEPENDENCIES]: Eliminate diagnostic noise. + 2011-10-11 Keith Marshall Fix --download-only vs. --reinstall conflict. diff --git a/src/pkgdeps.cpp b/src/pkgdeps.cpp index 2146f2b..d0c3745 100644 --- a/src/pkgdeps.cpp +++ b/src/pkgdeps.cpp @@ -166,14 +166,36 @@ const char *pkgXmlNode::GetContainerAttribute( const char *key, const char *sub return sub; } +DEBUG_INVOKED static int indent = -1; + DEBUG_INVOKED static void DEBUG_INVOKED show_required( pkgSpecs *req ) DEBUG_INVOKED { DEBUG_INVOKED const char *tarname = NULL; -DEBUG_INVOKED dmh_printf( " require: %s\n", req->GetTarName( tarname ) ); +DEBUG_INVOKED dmh_printf( "%*s require: %s\n", indent, "", req->GetTarName( tarname ) ); DEBUG_INVOKED free( (void *)(tarname) ); DEBUG_INVOKED } +static inline +bool is_abi_compatible( pkgSpecs *refdata, const char *version ) +{ + /* Local helper, used by pkgXmlDocument::ResolveDependencies(), + * to confirm that the ABI identification number of a selected + * component package is an exact match to a requirement spec. + */ + const char *ref_version; + if( (ref_version = refdata->GetComponentVersion()) == NULL ) + /* + * Here, confirm that both are unversioned... + */ + return (version == NULL); + + /* ...otherwise, fall through to check that both bear IDENTICALLY + * the same ABI version number. + */ + return ((version != NULL) && (strcmp( version, ref_version ) == 0)); +} + void pkgXmlDocument::ResolveDependencies( pkgXmlNode* package, pkgActionItem* rank ) # define promote( request, action ) (((request) & (~ACTION_MASK)) | action ) @@ -184,12 +206,11 @@ pkgXmlDocument::ResolveDependencies( pkgXmlNode* package, pkgActionItem* rank ) * of such prerequisites, and finally, extend the search to capture * additional dependencies common to the containing package group. */ - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( "ResolveDependencies: begin function\n" ) - ); pkgSpecs *refdata = NULL; pkgXmlNode *refpkg = package; + DEBUG_INVOKED ++indent; + while( package != NULL ) { /* We have a valid XML entity, which may identify dependencies; @@ -216,7 +237,7 @@ pkgXmlDocument::ResolveDependencies( pkgXmlNode* package, pkgActionItem* rank ) if( (refname = refpkg->GetPropVal( tarname_key, NULL )) != NULL ) { DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( "%s: resolve dependencies\n", refname ) + dmh_printf( "%*s%s: resolve dependencies\n", indent, "", refname ) ); refdata = new pkgSpecs( refname ); } @@ -267,26 +288,43 @@ pkgXmlDocument::ResolveDependencies( pkgXmlNode* package, pkgActionItem* rank ) /* ...noting if we find one already marked as "installed"... */ const char *tstclass; + DEBUG_INVOKED const char *already, *viable; pkgSpecs tst( tstclass = required->GetPropVal( tarname_key, NULL ) ); DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " considering: %s\n", tstclass ) + dmh_printf( "%*s considering: %s", indent, "", tstclass ) ); if( (tstclass = tst.GetComponentClass()) == NULL ) tstclass = value_unknown; - if( is_installed( required ) && (strcmp( tstclass, reqclass ) == 0) ) + DEBUG_INVOKED already = viable = ""; + if( is_installed( required ) && (strcmp( tstclass, reqclass ) == 0) + /* + * We found an installed version of the requisite component, + * but we ignore it unless it is ABI version compatible with + * the version we need; (the intent of ABI versioning is to + * accommodate multiple concurrent installations of shared + * objects supporting the differing ABI specifications). + */ + && is_abi_compatible( &tst, req.GetComponentVersion() ) ) + { installed = required; - + DEBUG_INVOKED already = " (already installed)"; + } /* ...and identify the most suitable candidate "release" * to satisfy the current dependency... */ if( wanted.SelectIfMostRecentFit( required ) == required ) + { selected = component = required; - + DEBUG_INVOKED viable = ": viable candidate"; + } /* ...continuing, until all available "releases" * have been evaluated accordingly. */ required = required->FindNextAssociate( release_key ); + DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), + dmh_printf( "%s%s\n", viable, already ) + ); } /* Where multiple component packages do exist, @@ -310,6 +348,11 @@ pkgXmlDocument::ResolveDependencies( pkgXmlNode* package, pkgActionItem* rank ) * version, we prefer to schedule an upgrade. */ fallback |= ACTION_UPGRADE; + DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), + dmh_printf( "%*s%s: schedule replacement\n", indent, "", + installed->GetPropVal( tarname_key, value_unknown ) + ) + ); wanted.SelectPackage( installed, to_remove ); } rank = Schedule( fallback, wanted, rank ); @@ -372,9 +415,7 @@ pkgXmlDocument::ResolveDependencies( pkgXmlNode* package, pkgActionItem* rank ) */ package = (package == GetRoot()) ? NULL : package->GetParent(); } - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( "ResolveDependencies: end function\n" ) - ); + DEBUG_INVOKED --indent; delete refdata; } @@ -593,12 +634,44 @@ void pkgXmlDocument::Schedule( unsigned long action, const char* name ) ResolveDependencies( upgrade, Schedule( action, latest )); else - /* attempting ACTION_UPGRADE or ACTION_REMOVE + { /* attempting ACTION_UPGRADE or ACTION_REMOVE * is an error; diagnose it. */ - dmh_notify( DMH_ERROR, "%s %s: package is not installed\n", - action_name( action & ACTION_MASK ), name - ); + if( component == NULL ) + /* + * In this case, the user explicitly specified a single + * package component, so it's a simple error... + */ + dmh_notify( DMH_ERROR, "%s %s: package is not installed\n", + action_name( action & ACTION_MASK ), name + ); + else + { + /* ...but here, the user specified only the package name, + * which implicitly applies to all associated components; + * since some may be installed, prefer to issue a warning + * in respect of any which aren't. + */ + const char *extname = component->GetPropVal( class_key, "" ); + char full_package_name[2 + strlen( name ) + strlen( extname )]; + sprintf( full_package_name, *extname ? "%s-%s" : "%s", name, extname ); + + dmh_control( DMH_BEGIN_DIGEST ); + dmh_notify( DMH_WARNING, "%s %s: request ignored...\n", + extname = action_name( action & ACTION_MASK ), full_package_name + ); + dmh_notify( DMH_WARNING, "%s: package was not previously installed\n", + full_package_name + ); + dmh_notify( DMH_WARNING, "%s: it will remain this way until you...\n", + full_package_name + ); + dmh_notify( DMH_WARNING, "use 'mingw-get install %s' to install it\n", + full_package_name + ); + dmh_control( DMH_END_DIGEST ); + } + } } else if( upgrade && (upgrade != installed) ) diff --git a/src/pkgexec.cpp b/src/pkgexec.cpp index bb24c32..399d2e0 100644 --- a/src/pkgexec.cpp +++ b/src/pkgexec.cpp @@ -278,9 +278,6 @@ pkgActionItem::GetReference( pkgActionItem& item ) pkgXmlNode *pkgActionItem::SelectIfMostRecentFit( pkgXmlNode *package ) { - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( "SelectIfMostRecentFit: begin function\n" ) - ); /* Assign "package" as the "selection" for the referring action item, * provided it matches the specified selection criteria and it represents * a more recent release than any current selection. @@ -318,9 +315,6 @@ pkgXmlNode *pkgActionItem::SelectIfMostRecentFit( pkgXmlNode *package ) /* Whatever choice we make, we return the resultant selection... */ - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( "SelectIfMostRecentFit: end function\n" ) - ); return Selection(); } diff --git a/src/pkgspec.cpp b/src/pkgspec.cpp index 3ae2739..198fab8 100644 --- a/src/pkgspec.cpp +++ b/src/pkgspec.cpp @@ -176,12 +176,6 @@ int pkgSpecs::VersionComparator( pkgSpecs& rhs ) const char *rhs_version_spec = rhs.GetPackageVersion(); const char *rhs_build_spec = rhs.GetPackageBuild(); - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " LHS: %s-%s-%s-%s\n RHS: %s-%s-%s-%s\n", - lhs_version_spec, lhs_build_spec, GetReleaseStatus(), GetReleaseIndex(), - rhs_version_spec, rhs_build_spec, rhs.GetReleaseStatus(), rhs.GetReleaseIndex()) - ); - /* Initially, we compare just the package version itself... */ pkgVersionInfo lhs_version( lhs_version_spec, lhs_build_spec ); @@ -193,10 +187,6 @@ int pkgSpecs::VersionComparator( pkgSpecs& rhs ) if( lhs_version < rhs_version ) return -1; if( lhs_version > rhs_version ) return +1; - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " base versions match\n" ) - ); - /* If we get to here, then the package versions of LHS and RHS * are effectively matched; however, unless there is a wildcard * specification in effect, (in which case we have an automatic @@ -224,9 +214,6 @@ int pkgSpecs::VersionComparator( pkgSpecs& rhs ) * same package version point, so we may immediately * confirm the LHS as the "lesser" release. */ - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " mismatched: LHS is qualified; RHS is not, and is not a wildcard\n" ) - ); return -1; } @@ -266,16 +253,9 @@ int pkgSpecs::VersionComparator( pkgSpecs& rhs ) * to a more recent release, so return the appropriate * value to indicate LHS > RHS. */ - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " mismatched: RHS qualified; LHS is not, and is not a wildcard\n" ) - ); return +1; } } - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " package versions match; checking subsystem\n" ) - ); - /* If we get to here, then LHS and RHS represent the same * version of the package, at the same phase of development; * the only remaining determinant, which may differentiate @@ -296,9 +276,6 @@ int pkgSpecs::VersionComparator( pkgSpecs& rhs ) * of any package version comparison, so we may return zero * to assert their equality. */ - DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_DEPENDENCIES ), - dmh_printf( " match found\n" ) - ); return 0; }