Problem running "cvs commit -m" inside a Perl script

N

Newshound

Hi all,

I'm trying to take a "cvs commit -m" command line with a multi-line
log message and run it inside a Perl script. For instance, trying to
run the command line:

prompt> cvs commit -m"This is a\
? multi-line log message." filename
prompt>

I would be trying to run this inside Perl as:

my $mesg = "\"This is a\\\nmulti-line log message."
RunCommand("cvs commit -m $mesg filename","commit.log");
....
sub RunCommand {
my $Command = shift;
my $Logfile = shift;
open(CMD_PIPE, "$Command |" )
open( LOG, ">$Logfile" )
while ( <CMD_PIPE> ) { print LOG $_; }
close( CMD_PIPE );
close( LOG )
}

There is some other stuff going on in the subroutine for stderr
redirection, skipping the command and just echoing it, etc., but
this captures the main point of the code.

The problem I am having is that this doesn't work correctly; it
always produces malformed log strings. I'm not a Perl jockey,
I know enough to get by, and the extra backslashes for multiple
layers of quoting sometimes confuse me, but I've tried the above
with various numbers of backslashes as well as splitting the
message string up into a concatenation of substrings to isolate
the newline, etc.

I just can't quite seem to find the right code. I'm trying to make
sure that a backslash is present to indicate the multi-line nature
of the message, as well as a newline to actually split the message
onto another line, but what cvs commit receives is not what I intend.

Can someone please help? I'd really appreciate it.

Thanks,
Mike
 
T

Tad McClellan

Newshound said:
my $mesg = "\"This is a\\\nmulti-line log message."
^^
^^

You have only one double quote character in your string.

Don't you want another one to delimit the end of the string?

You are also missing a semicolon at the end of that statement.
 
N

Newshound

Sorry, that was a typo on my part. I do actually have an escaped
double-quote at the end in my script, like so:

my $mesg = "\"This is a\\\nmulti-line log message.\""

Thanks for catching that.

--Mike

P.S.--I think I've gotten it somewhat working with a "here" document,
but it has some annoying side-effects I'd like to avoid if I can manage
to get the original code working.
 
P

Paul Lalli

Newshound said:
I'm trying to take a "cvs commit -m" command line with a multi-line
log message and run it inside a Perl script. For instance, trying to
run the command line:

prompt> cvs commit -m"This is a\
? multi-line log message." filename
prompt>

I would be trying to run this inside Perl as:

my $mesg = "\"This is a\\\nmulti-line log message."

As has already been pointed out, you have a typo here. Please copy and
paste your code, do not retype.

You're also making things harder for yourself than they have to be, by
using quoting delimiters that you actually want to have in your string.

You're also apparently not understanding that the \ in your original
shell command is merely an identifier to the shell that the command
didn't end when you pushed enter. There should not actually be a slash
there.

Write that command as either:
my $message = qq{"This is a\nmulti-line log message."};
or
my $message = '"This is a
multi-line log messsage"';
RunCommand("cvs commit -m $mesg filename","commit.log");
....
sub RunCommand {
my $Command = shift;
my $Logfile = shift;
open(CMD_PIPE, "$Command |" )

Where is the semi-colong that terminates this statement? Please copy
and paste your code, please do not retype.

Please do use lexical filehandles, not global barewords.

Please do check the return value of all system calls.

open my $CMD_PIPE, "$Command |" or die "Cannot start '$Command': $!";
open( LOG, ">$Logfile" )

All four of the previous comments apply here, plus, you should please
make sure to use the three-argument form of open:

open my $LOG, '>', $Logfile or die "Cannot open '$Logfile': $!";

Paul Lalli
 
A

anno4000

Newshound said:
Hi all,

I'm trying to take a "cvs commit -m" command line with a multi-line
log message and run it inside a Perl script. For instance, trying to
run the command line:

prompt> cvs commit -m"This is a\
? multi-line log message." filename
prompt>

I would be trying to run this inside Perl as:

my $mesg = "\"This is a\\\nmulti-line log message."

You're fighting the shell. Perhaps you can avoid it.
RunCommand("cvs commit -m $mesg filename","commit.log");
....
sub RunCommand {
my $Command = shift;
my $Logfile = shift;
open(CMD_PIPE, "$Command |" )
open( LOG, ">$Logfile" )
while ( <CMD_PIPE> ) { print LOG $_; }
close( CMD_PIPE );
close( LOG )
}

Don't re-type code, copy-paste is from a runnable source.

Use the list form for the command, that executes it without an
intervening shell. A command argument can be a multiline string
(indeed any binary string) without problems. Change the beginning
of RunCommand to (untested)

my @Command = @{ shift() };
my $Logfile = shift;
open(CMD_PIPE, '-|', @Command );

Try it with

RunCommand( [ 'echo', "one\ntwo\nthree"], '/tmp/log');

The multiline argument to "echo" should be exactly reproduced in
/tmp/log
There is some other stuff going on in the subroutine for stderr
redirection, ...

Now this could be the fly in the ointment because that's hard to
do without a shell. You can either cope with shell quoting (it's
doable, but I'm not going there), or fork and redirect yourself before
exec()ing @Command. IPC::Open3 deals with part of that (and then some
more).

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top