ensembl-hive  2.8.1
Programs.pm
Go to the documentation of this file.
1 =head1 LICENSE
2 
3 See the NOTICE file distributed with this work for additional information
4 regarding copyright ownership.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 =cut
19 
20 
21 =head1 CONTACT
22 
23  Please email comments or questions to the public Ensembl
24  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 
26  Questions may also be sent to the Ensembl help desk at
27  <http://www.ensembl.org/Help/Contact>.
28 
29 =cut
30 
31 package Bio::EnsEMBL::Analysis::Programs;
32 
33 use strict;
34 use vars qw( %Program_Paths );
35 use Carp;
36 use Cwd;
37 use Sys::Hostname;
38 use Bio::EnsEMBL::Utils::Exception qw ( throw ) ;
39 
40 sub import {
41  my $pkg = shift;
42  foreach (@_) {
43  #print STDERR "importing: $_\n";
44  $Program_Paths{ $_ } = 0;
45  }
46  my( $home, @PATH, @missing );
47 
48  $home = cwd() or die "Can't save cwd";
49  my $H = [ $home, 1 ];
50 
51  @PATH = split /:/, $ENV{'PATH'};
52  foreach (@PATH) {
53  s|/?$|/|; # Append / to each path
54  }
55 
56  # For each program, check there is an executable
57  foreach my $program (keys %Program_Paths) {
58 
59  # Deal with paths
60  if ($program =~ m|/|) {
61  _go_home( $H );
62  my $path = $program;
63  # Deal with tildes
64  $path =~ s{^~([^/]*)}{ $1 ? (getpwnam($1))[7]
65  : (getpwuid($>))[7] }e;
66  if (my $real = _is_prog( $H, $path )) {
67  $Program_Paths{ $program } = $real;
68  }
69  }
70  # Or search through all paths
71  else {
72  foreach my $path (@PATH) {
73  _go_home( $H );
74  if (my $real = _is_prog( $H, $path, $program )) {
75  $Program_Paths{ $program } = $real;
76  last;
77  }
78  }
79  }
80  }
81  _go_home( $H ); # Return to home directory
82 
83  # Make a list of all missing programs
84  foreach my $program (keys %Program_Paths) {
85  push( @missing, $program ) unless $Program_Paths{ $program };
86  }
87 
88  # Give informative death message if programs weren't found
89  if (@missing) {
90  throw("Unable to locate the following programs as '". (getpwuid($<))[0]. "' on host '". hostname(). "' :\t".
91  join ( " --> " , @missing )) ;
92  }
93 }
94 
95 # Recursive function which follows links, or tests final destination
96 sub _is_prog {
97  my( $h, $path, $prog ) = @_;
98 
99  # Need to split path if $prog not provided
100  unless ($prog) {
101  ($path, $prog) = $path =~ m|(.*?)([^/]+)$|;
102  }
103 
104  if (-l "$path$prog") {
105  # Follow link
106  _follow( $h, $path ) or return;
107  unless (-x readlink($prog)) {
108  confess "Can't read link '$path$prog' : $!";
109  }
110  my $link = $prog;
111  $path = cwd() or confess "Can't determine cwd";
112  return "$path/$prog";
113  } elsif (-f _ and -x _) {
114  # Return full path
115  _follow( $h, $path ) or return;
116  $path = cwd() or confess "Can't determine cwd";
117  return "$path/$prog";
118  } else {
119  # Not a link or an executable plain file
120  return;
121  }
122 }
123 
124 # To avoid unnecessary chdir'ing
125 sub _follow {
126  my( $H, $path ) = @_;
127 
128  # Chdir without arguments goes to home dir.
129  # Can't use defined in test since $path may contain
130  # a real null string.
131  if ( ! $path and $path ne '0' ) {
132  return 1;
133  } elsif (chdir($path)) {
134  $H->[1] = 0;
135  return 1;
136  } else {
137  return;
138  }
139 }
140 sub _go_home {
141  my( $H ) = @_;
142 
143  # Go home unless we're already there
144  if ($H->[1] == 0) {
145  if (chdir( $H->[0] )) {
146  $H->[1] = 1;
147  } else {
148  confess "Can't go home to [ ", $H->[0], ' ]';
149  }
150  }
151 }
152 
153 1;
154 
155 __END__
156 
157 =head1 NAME Programs
158 
159 =head1 SYSNOPSIS
160 
161  use Bio::EnsEMBL::Analysis::Programs qw( efetch getz est2genome
162  /usr/local/bin/this_one
163  ~me/some/path/my_prog
164  ~/../jane/bin/her_prog );
165 
166  # Can also do at run time
168 
169  $path_to_prog = $Bio::EnsEMBL::Analysis::Programs::Program_Paths{ $prog };
170 
171 =head1 DESCRIPTION
172 
173 B<Programs> is used to check at compile time for the
174 presence of executables which will be called from your
175 script. Arguments passed via the use statement
176 can be just the program name, or an absolute or
177 relative path to the program. Tildes are expanded
178 correctly (I<not> using "glob"). Failure to find any
179 one program is fatal, and a list of all failures is
180 printed, along with the host''s name.
181 
182 If you want to check for a program during run time,
183 the import funtion can be called directly, as shown above.
184 
185 The paths to each program found are stored in the
186 B<%Program_Paths> hash, which is keyed on the original
187 arguments passed.
188 
189 =head1 BUGS
190 
191 If the executable is in the root directory, then it''s found
192 path will appear as "//prog" in %Program_Paths, not "/prog".
193 
194 =head1 AUTHOR
195 
196 B<James Gilbert> Email jgrg@sanger.ac.uk
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
207 
Bio::EnsEMBL::Analysis::Programs::import
public import()
Bio::EnsEMBL::Analysis::Programs
Definition: Programs.pm:8
run
public run()
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68