2017-01-27 12:49:09 -08:00
# include "pch.h"
2016-09-22 23:28:50 -07:00
# include "vcpkg_Dependencies.h"
# include "vcpkg_Graphs.h"
2017-04-03 16:29:11 -07:00
# include "VcpkgPaths.h"
2017-04-03 14:45:00 -07:00
# include "PackageSpec.h"
2016-09-22 23:28:50 -07:00
# include "StatusParagraphs.h"
2016-11-07 16:38:49 -08:00
# include "vcpkg_Files.h"
2017-04-11 19:37:38 -07:00
# include "vcpkg_Util.h"
2016-09-22 23:28:50 -07:00
2017-01-05 14:14:11 -08:00
namespace vcpkg : : Dependencies
2016-09-22 23:28:50 -07:00
{
2017-04-11 19:37:38 -07:00
std : : vector < PackageSpec > AnyParagraph : : edges ( ) const
{
auto to_package_specs = [ & ] ( const std : : vector < std : : string > & dependencies_as_string )
{
return Util : : fmap ( dependencies_as_string , [ & ] ( const std : : string s )
{
return PackageSpec : : from_name_and_triplet ( s , this - > spec . triplet ( ) ) . value_or_exit ( VCPKG_LINE_INFO ) ;
} ) ;
} ;
if ( auto p = this - > status_paragraph . get ( ) )
{
return to_package_specs ( p - > package . depends ) ;
}
if ( auto p = this - > binary_paragraph . get ( ) )
{
return to_package_specs ( p - > depends ) ;
}
if ( auto p = this - > source_paragraph . get ( ) )
{
return to_package_specs ( filter_dependencies ( p - > depends , this - > spec . triplet ( ) ) ) ;
}
Checks : : exit_with_message ( VCPKG_LINE_INFO , " Cannot get dependencies for package %s because there was none of: source/binary/status paragraphs " , spec . to_string ( ) ) ;
}
2017-04-06 18:57:17 -07:00
std : : string to_output_string ( RequestType request_type , const CStringView s )
{
switch ( request_type )
{
2017-04-07 12:50:46 -07:00
case RequestType : : AUTO_SELECTED :
return Strings : : format ( " * %s " , s ) ;
case RequestType : : USER_REQUESTED :
return Strings : : format ( " %s " , s ) ;
default :
Checks : : unreachable ( VCPKG_LINE_INFO ) ;
2017-04-06 18:57:17 -07:00
}
}
2017-04-11 19:37:38 -07:00
InstallPlanAction : : InstallPlanAction ( ) : plan_type ( InstallPlanType : : UNKNOWN )
, request_type ( RequestType : : UNKNOWN )
, binary_pgh ( nullopt )
, source_pgh ( nullopt ) { }
InstallPlanAction : : InstallPlanAction ( const AnyParagraph & any_paragraph , const RequestType & request_type ) : InstallPlanAction ( )
{
this - > request_type = request_type ;
if ( any_paragraph . status_paragraph . get ( ) )
{
this - > plan_type = InstallPlanType : : ALREADY_INSTALLED ;
return ;
}
if ( auto p = any_paragraph . binary_paragraph . get ( ) )
{
this - > plan_type = InstallPlanType : : INSTALL ;
this - > binary_pgh = * p ;
return ;
}
if ( auto p = any_paragraph . source_paragraph . get ( ) )
{
this - > plan_type = InstallPlanType : : BUILD_AND_INSTALL ;
this - > source_pgh = * p ;
return ;
}
this - > plan_type = InstallPlanType : : UNKNOWN ;
}
2017-04-07 13:03:11 -07:00
InstallPlanAction : : InstallPlanAction ( const InstallPlanType & plan_type , const RequestType & request_type , Optional < BinaryParagraph > binary_pgh , Optional < SourceParagraph > source_pgh )
2017-04-11 19:37:38 -07:00
: plan_type ( std : : move ( plan_type ) )
, request_type ( request_type )
, binary_pgh ( std : : move ( binary_pgh ) )
, source_pgh ( std : : move ( source_pgh ) ) { }
2017-01-30 17:52:53 -08:00
2017-04-07 13:02:50 -07:00
bool PackageSpecWithInstallPlan : : compare_by_name ( const PackageSpecWithInstallPlan * left , const PackageSpecWithInstallPlan * right )
{
return left - > spec . name ( ) < right - > spec . name ( ) ;
}
2017-01-30 17:52:53 -08:00
2017-04-11 19:37:38 -07:00
PackageSpecWithInstallPlan : : PackageSpecWithInstallPlan ( const PackageSpec & spec , InstallPlanAction & & plan )
: spec ( spec )
, plan ( std : : move ( plan ) ) { }
2017-01-30 17:52:53 -08:00
2017-04-11 19:37:38 -07:00
RemovePlanAction : : RemovePlanAction ( ) : plan_type ( RemovePlanType : : UNKNOWN )
, request_type ( RequestType : : UNKNOWN ) { }
2017-01-30 17:52:53 -08:00
2017-04-11 19:37:38 -07:00
RemovePlanAction : : RemovePlanAction ( const RemovePlanType & plan_type , const RequestType & request_type )
: plan_type ( plan_type )
, request_type ( request_type ) { }
2017-01-30 17:52:53 -08:00
2017-04-06 17:37:19 -07:00
bool PackageSpecWithRemovePlan : : compare_by_name ( const PackageSpecWithRemovePlan * left , const PackageSpecWithRemovePlan * right )
{
return left - > spec . name ( ) < right - > spec . name ( ) ;
}
2017-04-03 16:24:44 -07:00
PackageSpecWithRemovePlan : : PackageSpecWithRemovePlan ( const PackageSpec & spec , RemovePlanAction & & plan )
2017-04-11 19:37:38 -07:00
: spec ( spec )
, plan ( std : : move ( plan ) ) { }
2017-01-30 17:52:53 -08:00
2017-04-03 16:29:11 -07:00
std : : vector < PackageSpecWithInstallPlan > create_install_plan ( const VcpkgPaths & paths , const std : : vector < PackageSpec > & specs , const StatusParagraphs & status_db )
2016-11-07 17:05:32 -08:00
{
2017-04-11 19:37:38 -07:00
struct InstallAdjacencyProvider final : Graphs : : AdjacencyProvider < PackageSpec , AnyParagraph >
2016-09-22 23:28:50 -07:00
{
2017-04-11 19:37:38 -07:00
const VcpkgPaths & paths ;
const StatusParagraphs & status_db ;
2016-09-22 23:28:50 -07:00
2017-04-11 19:37:38 -07:00
InstallAdjacencyProvider ( const VcpkgPaths & p , const StatusParagraphs & s ) : paths ( p )
, status_db ( s ) { }
2016-09-22 23:28:50 -07:00
2017-04-11 19:37:38 -07:00
std : : vector < PackageSpec > adjacency_list ( const AnyParagraph & p ) const override
2016-09-22 23:28:50 -07:00
{
2017-04-11 19:37:38 -07:00
if ( p . status_paragraph . get ( ) )
return std : : vector < PackageSpec > { } ;
return p . edges ( ) ;
2016-11-15 11:56:46 -08:00
}
2016-10-04 15:25:53 -07:00
2017-04-11 19:37:38 -07:00
AnyParagraph load_vertex_data ( const PackageSpec & spec ) const override
2016-11-15 11:56:46 -08:00
{
2017-04-11 19:37:38 -07:00
auto it = status_db . find_installed ( spec ) ;
if ( it ! = status_db . end ( ) )
return { spec , * it - > get ( ) , nullopt , nullopt } ;
2016-09-22 23:28:50 -07:00
2017-04-11 19:37:38 -07:00
Expected < BinaryParagraph > maybe_bpgh = Paragraphs : : try_load_cached_package ( paths , spec ) ;
if ( auto bpgh = maybe_bpgh . get ( ) )
return { spec , nullopt , * bpgh , nullopt } ;
Expected < SourceParagraph > maybe_spgh = Paragraphs : : try_load_port ( paths . port_dir ( spec ) ) ;
if ( auto spgh = maybe_spgh . get ( ) )
return { spec , nullopt , nullopt , * spgh } ;
return { spec , nullopt , nullopt , nullopt } ;
2017-03-31 09:26:58 -07:00
}
2017-04-11 19:37:38 -07:00
} ;
2016-09-22 23:28:50 -07:00
2017-04-11 19:37:38 -07:00
auto toposort = Graphs : : topological_sort ( specs , InstallAdjacencyProvider { paths , status_db } ) ;
2016-11-07 16:38:49 -08:00
2017-04-12 16:24:49 -07:00
std : : unordered_set < PackageSpec > specs_as_set ( specs . cbegin ( ) , specs . cend ( ) ) ;
2017-04-11 19:37:38 -07:00
std : : vector < PackageSpecWithInstallPlan > ret ;
for ( const AnyParagraph & pkg : toposort )
2016-11-07 16:38:49 -08:00
{
2017-04-11 19:37:38 -07:00
auto spec = pkg . spec ;
const RequestType request_type = specs_as_set . find ( spec ) ! = specs_as_set . end ( ) ? RequestType : : USER_REQUESTED : RequestType : : AUTO_SELECTED ;
if ( pkg . status_paragraph & & request_type ! = RequestType : : USER_REQUESTED )
continue ;
InstallPlanAction a ( pkg , request_type ) ;
ret . push_back ( PackageSpecWithInstallPlan ( spec , std : : move ( a ) ) ) ;
2016-11-07 16:38:49 -08:00
}
2016-11-15 11:56:46 -08:00
return ret ;
2016-11-07 16:38:49 -08:00
}
2017-01-26 17:53:45 -08:00
2017-04-03 16:24:44 -07:00
std : : vector < PackageSpecWithRemovePlan > create_remove_plan ( const std : : vector < PackageSpec > & specs , const StatusParagraphs & status_db )
2017-01-26 17:53:45 -08:00
{
2017-04-03 14:45:00 -07:00
std : : unordered_set < PackageSpec > specs_as_set ( specs . cbegin ( ) , specs . cend ( ) ) ;
2017-01-26 17:53:45 -08:00
2017-04-03 16:24:18 -07:00
std : : unordered_map < PackageSpec , RemovePlanAction > was_examined ; // Examine = we have checked its immediate (non-recursive) dependencies
2017-04-03 14:45:00 -07:00
Graphs : : Graph < PackageSpec > graph ;
2017-01-26 17:53:45 -08:00
graph . add_vertices ( specs ) ;
2017-04-03 14:45:00 -07:00
std : : vector < PackageSpec > examine_stack ( specs ) ;
2017-01-26 17:53:45 -08:00
while ( ! examine_stack . empty ( ) )
{
2017-04-03 14:45:00 -07:00
const PackageSpec spec = examine_stack . back ( ) ;
2017-01-26 17:53:45 -08:00
examine_stack . pop_back ( ) ;
if ( was_examined . find ( spec ) ! = was_examined . end ( ) )
{
continue ;
}
2017-04-12 16:16:57 -07:00
const StatusParagraphs : : const_iterator it = status_db . find_installed ( spec ) ;
if ( it = = status_db . end ( ) )
2017-01-26 17:53:45 -08:00
{
2017-04-03 16:24:18 -07:00
was_examined . emplace ( spec , RemovePlanAction ( RemovePlanType : : NOT_INSTALLED , RequestType : : USER_REQUESTED ) ) ;
2017-01-26 17:53:45 -08:00
continue ;
}
2017-04-12 16:19:52 -07:00
const std : : vector < StatusParagraph * > installed_ports = get_installed_ports ( status_db ) ;
for ( const StatusParagraph * an_installed_package : installed_ports )
2017-01-26 17:53:45 -08:00
{
2017-04-10 13:03:34 -07:00
if ( an_installed_package - > package . spec . triplet ( ) ! = spec . triplet ( ) )
2017-01-26 17:53:45 -08:00
continue ;
const std : : vector < std : : string > & deps = an_installed_package - > package . depends ;
if ( std : : find ( deps . begin ( ) , deps . end ( ) , spec . name ( ) ) = = deps . end ( ) )
{
continue ;
}
2017-04-12 16:19:52 -07:00
graph . add_edge ( spec , an_installed_package - > package . spec ) ;
examine_stack . push_back ( an_installed_package - > package . spec ) ;
2017-01-26 17:53:45 -08:00
}
2017-04-03 16:21:46 -07:00
const RequestType request_type = specs_as_set . find ( spec ) ! = specs_as_set . end ( ) ? RequestType : : USER_REQUESTED : RequestType : : AUTO_SELECTED ;
2017-04-03 16:24:18 -07:00
was_examined . emplace ( spec , RemovePlanAction ( RemovePlanType : : REMOVE , request_type ) ) ;
2017-01-26 17:53:45 -08:00
}
2017-04-03 16:24:44 -07:00
std : : vector < PackageSpecWithRemovePlan > ret ;
2017-01-26 17:53:45 -08:00
2017-04-11 14:30:49 -07:00
const std : : vector < PackageSpec > pkgs = graph . topological_sort ( ) ;
2017-04-03 14:45:00 -07:00
for ( const PackageSpec & pkg : pkgs )
2017-01-26 17:53:45 -08:00
{
2017-04-03 16:24:44 -07:00
ret . push_back ( PackageSpecWithRemovePlan ( pkg , std : : move ( was_examined [ pkg ] ) ) ) ;
2017-01-26 17:53:45 -08:00
}
return ret ;
}
2017-01-05 14:14:11 -08:00
}