File Coverage

blib/lib/Sman/Util.pm
Criterion Covered Total %
statement 36 136 26.4
branch 0 42 0.0
condition 0 7 0.0
subroutine 12 22 54.5
pod 0 10 0.0
total 48 217 22.1


line stmt bran cond sub pod time code
1             ################################
2             package Sman::Util;
3 1     1   691 use Sman; # for VERSION
  1         2  
  1         20  
4              
5 1     1   3 use strict;
  1         1  
  1         15  
6 1     1   2 use warnings;
  1         1  
  1         17  
7 1     1   3 use Config; # to get perl version string
  1         1  
  1         27  
8 1     1   581 use File::Temp; # used in RunCommand()
  1         12377  
  1         58  
9 1     1   747 use IPC::Run qw( run timeout );
  1         23845  
  1         45  
10 1     1   382 use version;
  1         1225  
  1         4  
11              
12             our $VERSION = '1.04';
13             our $SMAN_DATA_VERSION = "1.4"; # this is only relevant to Sman
14              
15             # TODO: FIX THIS, to not hard code dirs
16 1     1   481 use lib '/usr/local/lib/swish-e/perl'; # for source installs, so we can find SWISH::DefaultHighlight.pm
  1         438  
  1         4  
17 1     1   114 use lib '/usr/libexec/swish-e/perl/'; # for rpm installs, so we can find SWISH::DefaultHighlight.pm
  1         2  
  1         3  
18 1     1   91 use lib '/sw/lib/swish-e/perl'; # for fink-installed SWISH::DefaultHightlight. TODO: cleanup.
  1         1  
  1         2  
19              
20             # this checks if the SWISH::API is recent enough to have
21             # the features we use. returns 1 if yes, 0 otherwise
22             sub CheckSwisheVersion {
23             #eval { # wrap the version check in an EVAL in case of failure
24             # require SWISH::API;
25             # no strict 'vars';
26             # use vars qw( $SWISH::API::VERSION );
27             # unless ($SWISH::API::VERSION && $SWISH::API::VERSION >= 0.03) {
28             # $@ = "Can't run: need SWISH::API >= 0.03\n";
29             # return 0;
30             # }
31             #};
32 0     0 0   my $class = "SWISH::API";
33 0           eval "require $class"; # if the class exists, this should load it
34            
35 0 0         if ($@) {
36 0           warn "$0: Can't load $class\n";
37 0           return 0;
38             }
39              
40 1     1   166 no strict 'vars';
  1         1  
  1         22  
41 1     1   3 use vars qw( $SWISH::API::VERSION );
  1         1  
  1         1100  
42 0 0 0       unless ($SWISH::API::VERSION && version->new($SWISH::API::VERSION) >= 0.03) {
43             # PAUSE namespace indexer complains about the line above:
44             # " The PAUSE indexer was not able to parse the following line
45             # in that file: C< unless ($SWISH::API::VERSION &&
46             # $SWISH::API::VERSION >= 0.03) { > Note: the indexer is
47             # running in a Safe compartement and cannot provide the full
48             # functionality of perl in the VERSION line. It is trying
49             # hard, but sometime it fails. As a workaround, please
50             # consider writing a proper META.yml that contains a
51             # 'provides' attribute (currently only supported by
52             # Module::Build) or contact the CPAN admins to investigate
53             # (yet another) workaround against "Safe" limitations.) "
54              
55             # I don't understand why the namespace indexer needs to parse (run) this function
56              
57 0           warn "$0: Can't run: need SWISH::API >= 0.03\n";
58 0           $@ = "Can't run: need SWISH::API >= 0.03\n"; # SET $@ for caller, if they check
59 0           return 0;
60             }
61 0           return 1; # it's OK
62             }
63              
64             sub MakeXML { # output xml version of hash
65 0     0 0   my $metas = shift;
66             my $xml = join ("",
67 0           map { "<$_>\n" . XMLEscape($metas->{$_}) . "\n\n" }
  0            
68             keys %$metas);
69 0           my $pre = qq{\n\n};
70 0           return qq{$pre\n$xml\n\n};
71             }
72              
73             sub XMLEscape {
74 0 0   0 0   return "" unless defined($_[0]);
75 0           my $v = shift;
76 0           $v =~ s/&/&/g;
77 0           $v =~ s/
78 0           $v =~ s/>/>/g;
79 0           return $v;
80             }
81              
82             # like File::Slurp::read_file()
83             sub ReadFile {
84 0     0 0   my $file = shift;
85 0           local( $/, *FFF ); # $/ is set to undef
86 0 0 0       open(FFF, "<", $file) || warn "Couldn't open $file: $!" && return "";
87 0           my $content = ; # file slurped at once
88 0 0         close(FFF) || warn "Error closing $file: $!";
89 0           return $content;
90             }
91             # like File::Slurp::write_file()
92             sub WriteFile {
93 0     0 0   my ($file, $contentref) = @_;
94 0 0 0       open(my $fh, ">", "$file") || warn "Couldn't open $file: $!" && return 0;
95 0           print $fh $$contentref;
96 0 0         close($fh) || warn "Error closing $file: $!";
97 0           return $contentref;
98             }
99              
100              
101             # given a command and optional tmpdir, returns (stdout, stderr, $?)
102             # uses IPC::Run::run() underneath
103             sub RunCommandNew {
104 0     0 0   my ($cmd_ref, $tmpdir, $should_be_undef) = @_;
105 0           my @cmd = @$cmd_ref;
106              
107 0 0         die "$0: Internal Error: Sman::Util::RunCommand called with three arguments\n"
108             if $should_be_undef;
109 0 0         $tmpdir = "/tmp" unless defined $tmpdir;
110              
111             #my @cmd = ($cmd);
112 0           my ($in, $out, $err) = ("", "", "");
113 0           run( \@cmd, \$in, \$out, \$err , timeout( 30 ) );
114 0           return ( $out, $err, $? );
115             }
116              
117             # RunCommand's block, to encapsulate @tmpfiles.
118             {
119             my @tmpfiles = ();
120             # given a command and optional tmpdir, returns (stdout, stderr, $?)
121             # uses the shell underneath
122             sub RunCommand {
123 0     0 0   my ($cmd, $tmpdir, $should_be_undef) = @_;
124 0 0         die "$0: Internal Error: Sman::Util::RunCommand called with three arguments\n"
125             if $should_be_undef;
126 0 0         $tmpdir = "/tmp" unless defined $tmpdir;
127 0           my ($out, $err) = ("", "");
128 0           my $r = sprintf("%04d", rand(9999));
129 0           my ($ofh, $outfile) = File::Temp::tempfile( "cmd-out.XXXXX", DIR => $tmpdir);
130 0           my ($efh, $errfile) = File::Temp::tempfile( "cmd-err.XXXXX", DIR => $tmpdir);
131             # use two temporary filenames
132 0           my $torun = "$cmd 1>$outfile 2>$errfile";
133 0           push(@tmpfiles, $outfile, $errfile); # in case of SIG
134             #print "RUNNING $torun\n";
135 0           system($torun);
136 0 0         if ($?) {
137 0           my $exit = $? >> 8;
138 0           my $signal = $? & 127;
139 0           my $dumped = $? & 128;
140              
141 0           $err .= "** ERROR: $torun\n";
142 0           $err .= "exitvalue $exit";
143 0 0         $err .= ", got signal $signal" if $signal;
144 0 0         $err .= ", dumped core" if $dumped;
145 0           $err .= "\n";
146             }
147 0           my $dollarquestionmark = $?;
148            
149 0           $out .= ReadFile($outfile);
150 0           $err .= ReadFile($errfile);
151              
152 0 0         unlink($errfile) || warn "$0: couldn't unlink $errfile: $!";
153 0           pop(@tmpfiles);
154 0 0         unlink($outfile) || warn "$0: couldn't unlink $outfile: $!";
155 0           pop(@tmpfiles);
156              
157 0           return ($out, $err, $dollarquestionmark);
158             }
159             END { # hopefully this will get triggered
160             # if RunCommand throws an exception
161             for my $tmpfile (@tmpfiles) {
162             unlink($tmpfile) || warn "** Couldn't unlink tmp file $tmpfile";
163             }
164             }
165             }
166              
167             sub GetIndexDescriptionString {
168 0     0 0   my ($index) = @_;
169 0           my $indexmodtime = (stat( "$index.prop" ))[9];
170 0 0         return sprintf("Using index %s, %s\n",
171             $index, $indexmodtime ? "updated " . scalar(localtime( $indexmodtime ) ) : "(index not found)" );
172             }
173              
174             sub GetVersionString {
175 0     0 0   my ($prog, $swishecmd) = @_;
176 0           require SWISH::API; # for $VERSION
177 0           require Sman; # for $VERSION
178 0           my $str = "$prog $Sman::Util::VERSION, using SWISH::API $SWISH::API::VERSION";
179 0 0         if ($swishecmd) {
180 0           my $cmd = $swishecmd . " -V";
181 0           my @lines = `$cmd`;
182 0 0         if (defined($lines[0])) {
183 0           chomp($lines[0]);
184 0 0         ($lines[0] =~ / ([\d.]+)/) && ($lines[0] = "Swish-e $1");
185 0           $str .= ", $lines[0]";
186             }
187             }
188 0           $str .= ", and perl $Config{version}";
189 0           return $str;
190             }
191              
192              
193             sub ExtractSummary {
194 0     0 0   require SWISH::DefaultHighlight; # defer till now, so sman -V doesn't need SWISH::API
195 0           my %header = (
196             wordcharacters => q{0123456789abcdefghijklmnopqrstuvwxyz});
197             #q{ªµºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞß} .
198             #q{àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ});
199 0           my %highlight = (
200             show_words => 4, # Number of "swish words" words to show around highlighted word
201             max_words => 10, # If no words are found to highlighted then show this many words
202             occurrences => 4, # Limit number of occurrences of highlighted words
203             highlight_on => '*', # highlighting code
204             highlight_off => '*',
205             );
206              
207 0           my ($str, $termsref, $prefix, $width) = @_;
208 0           my $sho = new SWISH::DefaultHighlight( \%highlight, \%header );
209             #my $sho = new SWISH::SimpleHighlight( \%highlight, \%header );
210 0           my @phrases;
211 0           for my $t (@$termsref) {
212 0           my @list = ($t);
213 0           push(@phrases, \@list);
214             }
215 0           $sho->highlight(\$str, \@phrases, 'swishdescription');
216 0           $str =~ s/"/'/g;
217 0           $str =~ s/>/>/g;
218 0           $str =~ s/</
219 0           $str =~ s/^\s+//;
220 0           $str =~ s/\s+$//;
221 0           $str = $prefix . $str;
222 0 0         $str = substr($str, 0, $width-3) . "..." if length($str) > $width;
223 0           return $str;
224             }
225              
226              
227             1;
228              
229             =pod
230              
231             =encoding utf-8
232              
233             =head1 NAME
234              
235             Sman::Util - Utility functions for Sman
236              
237             =head1 SYNOPSIS
238              
239             Sman::Util currently provides the following functions:
240              
241             # XMLEscape escapes XML
242             my $str = Sman::Util::XMLEscape("a-fun#y&%$TRiñg");
243            
244             # MakeXML makes XML from a simple hash of names->strings
245             my $xml = Sman::Util::MakeXML(\%somehash);
246            
247             # ReadFile reads the contents of a file and returns it as a scalar
248             my $content = Sman::Util::ReadFile("filename");
249            
250             # RunCommand uses the shell to capture stdout and stderr and $?
251             # Pass command and tempdir to save its temp files in.
252             # tmpdir defaults to '/tmp'
253             my ($out, $err, $dollarquestionmark) = Sman::Util::RunCommand("ls -l", "/tmp");
254              
255             # GetVersionString gives you a version string like
256             # 'sman v0.8.3 using SWISH::API v0.01 and Swish-e v2.4.0'
257             # pass program name and the Swish-e command path
258             my $vstr = Sman::Util::GetVersionString('prog', '/usr/local/bin/swish-e');
259            
260             =head1 DESCRIPTION
261              
262             This module implements utility functions for sman-update and sman
263              
264             =head1 AUTHOR
265              
266             Copyright Josh Rabinowitz 2004-2016
267              
268             =head1 SEE ALSO
269              
270             L, L
271              
272             =cut
273