File Coverage

blib/lib/R/Setup/Resolve.pm
Criterion Covered Total %
statement 12 76 15.7
branch 0 20 0.0
condition 0 2 0.0
subroutine 5 13 38.4
pod 0 8 0.0
total 17 119 14.2


line stmt bran cond sub pod time code
1             # perl program
2             # R instance with Internet connection
3             # accept: a list of package ids
4             # processes:
5             # - reads package todo list (package id)
6             # - gets 'depends' and 'imports' list for each package id
7             # - constructs a linear list in order of deps
8             #
9             # Copyright (C) 2015, Snehasis Sinha
10             #
11              
12             package R::Setup::Resolve;
13              
14 2     2   20856 use 5.010001;
  2         7  
15 2     2   10 use strict;
  2         3  
  2         44  
16 2     2   9 use warnings;
  2         3  
  2         54  
17 2     2   1734 use IPC::Open3;
  2         9050  
  2         159  
18              
19             our @ISA = qw();
20             our $VERSION = '0.01';
21              
22              
23             # Preloaded methods go here.
24 2     2   1697 BEGIN { $| = 1 }
25              
26             sub new {
27 0     0 0   my $class = shift;
28 0           my %params = @_;
29             my $self = {
30             _rbin => 'R -q --no-save', # R command, should be in $PATH
31             _packages=> $params{'packages'}, # array ref of packages wishlist
32             _final => undef, # final list is stored in order
33             _tree => undef, # tree of packages with children as dependencies
34             _dhash => undef, # dumb hash to generate unique list
35 0   0       _verbose => $params{'verbose'} || 1, # default: yes
36             };
37 0           bless $self, $class;
38 0           return $self;
39             }
40              
41             # get dep list for a package
42             # returns list, accepts package id
43             # package=>pkgname
44             sub p_r_program {
45 0     0 0   my ($self, %arg) = (@_);
46 0           my $findr = qq|
47             options(repos=structure(c(CRAN="http://cran.r-project.org/")))
48              
49             getPackages <- function(packs){
50             packages <- unlist(
51             tools::package_dependencies(
52             packs,
53             available.packages(),
54             which=c("Depends", "Imports"),
55             recursive=TRUE
56             )
57             )
58             packages <- union(packs, packages)
59             packages
60             }
61              
62             pkgs <- getPackages (c("$arg{name}"))
63             pkgs
64             |;
65 0           return $findr;
66             }
67              
68             sub get_package_deps {
69 0     0 0   my ($self, %arg) = (@_);
70 0           my @list=();
71 0           my @pkgs=();
72 0           my $i=0;
73 0           my $findr = $self->p_r_program ( name => $arg{name} );
74 0           my $output="";
75              
76 0 0         my $pid = open3 ( \*INPUT, \*OUTPUT, \*ERROR, $self->{'_rbin'} ) or die $!;
77 0           print INPUT $findr;
78 0           close INPUT;
79              
80 0           while ( ) {
81 0 0         next if m/^\>/;
82 0 0         next if m/^\+/;
83 0           chomp;
84 0           $output.=" ".$_;
85             }
86 0           close OUTPUT;
87 0           close ERROR;
88              
89 0           @pkgs = split /\s+/, $output;
90              
91 0           foreach (@pkgs) {
92 0 0         next if m/^$/;
93 0 0         next if m/^\[/;
94 0           $_ =~ s/\"//g;
95              
96 0 0         if ( $i eq 0 ) {
97 0           $i++;
98 0           next;
99             }
100 0           push (@list, $_);
101             }
102 0           print join ' ', @list, "\n";
103 0           return \@list;
104             }
105              
106             sub p_create_tree {
107 0     0 0   my ($self, %args) = (@_);
108 0           my $list;
109              
110 0 0         unless (exists $self->{'_tree'}->{ $args{name} }) {
111 0 0         print "resolving deps for ".$args{name}." ...\n" if $self->{'_verbose'};
112 0           $self->{'_tree'}->{ $args{name} } = $self->get_package_deps ( name => $args{name} );
113             }
114              
115 0           foreach my $p ( @{$self->{'_tree'}->{ $args{name} } } ) {
  0            
116 0           $self->p_create_tree ( name => $p );
117             }
118             }
119              
120             sub p_create_trees {
121             # merge all lists
122 0     0 0   my ($self) = (@_);
123              
124 0           foreach my $p ( @{$self->{'_packages'}} ) {
  0            
125 0           $self->p_create_tree ( name => $p );
126             }
127             }
128              
129             sub p_set_node {
130 0     0 0   my ($self, $node) = (@_);
131              
132 0 0         return unless exists $self->{'_tree'}->{$node};
133 0 0         return if exists $self->{'_dhash'}->{$node};
134              
135 0           foreach my $e ( @{$self->{'_tree'}->{$node}} ) {
  0            
136 0           $self->p_set_node ( $e );
137             }
138              
139 0           push ( @{$self->{'_final'}}, $node );
  0            
140 0           $self->{'_dhash'}->{$node} = 1;
141             }
142              
143             sub p_set_nodes {
144 0     0 0   my ($self) = (@_);
145            
146 0           foreach ( @{$self->{'_packages'}} ) {
  0            
147 0           $self->p_set_node ( $_ );
148             }
149             }
150            
151             sub resolve {
152 0     0 0   my ($self) = (@_);
153              
154 0           $self->p_create_trees;
155 0           $self->p_set_nodes;
156              
157 0           return $self->{'_final'};
158             }
159              
160             1;
161              
162             __END__