ensembl-hive  2.7.0
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 use strict;
33 use vars qw( %Program_Paths );
34 use Carp;
35 use Cwd;
36 use Sys::Hostname;
37 use Bio::EnsEMBL::Utils::Exception qw ( throw ) ;
38 
39 sub import {
40  my $pkg = shift;
41  foreach (@_) {
42  #print STDERR "importing: $_\n";
43  $Program_Paths{ $_ } = 0;
44  }
45  my( $home, @PATH, @missing );
46 
47  $home = cwd() or die "Can't save cwd";
48  my $H = [ $home, 1 ];
49 
50  @PATH = split /:/, $ENV{'PATH'};
51  foreach (@PATH) {
52  s|/?$|/|; # Append / to each path
53  }
54 
55  # For each program, check there is an executable
56  foreach my $program (keys %Program_Paths) {
57 
58  # Deal with paths
59  if ($program =~ m|/|) {
60  _go_home( $H );
61  my $path = $program;
62  # Deal with tildes
63  $path =~ s{^~([^/]*)}{ $1 ? (getpwnam($1))[7]
64  : (getpwuid($>))[7] }e;
65  if (my $real = _is_prog( $H, $path )) {
66  $Program_Paths{ $program } = $real;
67  }
68  }
69  # Or search through all paths
70  else {
71  foreach my $path (@PATH) {
72  _go_home( $H );
73  if (my $real = _is_prog( $H, $path, $program )) {
74  $Program_Paths{ $program } = $real;
75  last;
76  }
77  }
78  }
79  }
80  _go_home( $H ); # Return to home directory
81 
82  # Make a list of all missing programs
83  foreach my $program (keys %Program_Paths) {
84  push( @missing, $program ) unless $Program_Paths{ $program };
85  }
86 
87  # Give informative death message if programs weren't found
88  if (@missing) {
89  throw("Unable to locate the following programs as '". (getpwuid($<))[0]. "' on host '". hostname(). "' :\t".
90  join ( " --> " , @missing )) ;
91  }
92 }
93 
94 # Recursive function which follows links, or tests final destination
95 sub _is_prog {
96  my( $h, $path, $prog ) = @_;
97 
98  # Need to split path if $prog not provided
99  unless ($prog) {
100  ($path, $prog) = $path =~ m|(.*?)([^/]+)$|;
101  }
102 
103  if (-l "$path$prog") {
104  # Follow link
105  _follow( $h, $path ) or return;
106  unless (-x readlink($prog)) {
107  confess "Can't read link '$path$prog' : $!";
108  }
109  my $link = $prog;
110  $path = cwd() or confess "Can't determine cwd";
111  return "$path/$prog";
112  } elsif (-f _ and -x _) {
113  # Return full path
114  _follow( $h, $path ) or return;
115  $path = cwd() or confess "Can't determine cwd";
116  return "$path/$prog";
117  } else {
118  # Not a link or an executable plain file
119  return;
120  }
121 }
122 
123 # To avoid unnecessary chdir'ing
124 sub _follow {
125  my( $H, $path ) = @_;
126 
127  # Chdir without arguments goes to home dir.
128  # Can't use defined in test since $path may contain
129  # a real null string.
130  if ( ! $path and $path ne '0' ) {
131  return 1;
132  } elsif (chdir($path)) {
133  $H->[1] = 0;
134  return 1;
135  } else {
136  return;
137  }
138 }
139 sub _go_home {
140  my( $H ) = @_;
141 
142  # Go home unless we're already there
143  if ($H->[1] == 0) {
144  if (chdir( $H->[0] )) {
145  $H->[1] = 1;
146  } else {
147  confess "Can't go home to [ ", $H->[0], ' ]';
148  }
149  }
150 }
151 
152 1;
153 
154 __END__
155 
156 =head1 NAME Programs
157 
158 =head1 SYSNOPSIS
159 
160  use Bio::EnsEMBL::Analysis::Programs qw( efetch getz est2genome
161  /usr/local/bin/this_one
162  ~me/some/path/my_prog
163  ~/../jane/bin/her_prog );
164 
165  # Can also do at run time
167 
168  $path_to_prog = $Bio::EnsEMBL::Analysis::Programs::Program_Paths{ $prog };
169 
170 =head1 DESCRIPTION
171 
172 B<Programs> is used to check at compile time for the
173 presence of executables which will be called from your
174 script. Arguments passed via the use statement
175 can be just the program name, or an absolute or
176 relative path to the program. Tildes are expanded
177 correctly (I<not> using "glob"). Failure to find any
178 one program is fatal, and a list of all failures is
179 printed, along with the host''s name.
180 
181 If you want to check for a program during run time,
182 the import funtion can be called directly, as shown above.
183 
184 The paths to each program found are stored in the
185 B<%Program_Paths> hash, which is keyed on the original
186 arguments passed.
187 
188 =head1 BUGS
189 
190 If the executable is in the root directory, then it''s found
191 path will appear as "//prog" in %Program_Paths, not "/prog".
192 
193 =head1 AUTHOR
194 
195 B<James Gilbert> Email jgrg@sanger.ac.uk
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
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