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

Discussion in 'Perl Misc' started by Newshound, Oct 2, 2006.

  1. Newshound

    Newshound Guest

    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
     
    Newshound, Oct 2, 2006
    #1
    1. Advertising

  2. Newshound <> wrote:

    > 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.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Oct 2, 2006
    #2
    1. Advertising

  3. Newshound

    Newshound Guest

    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.


    Tad McClellan wrote:
    > Newshound <> wrote:
    >
    > > 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.
    >
    >
    > --
    > Tad McClellan SGML consulting
    > Perl programming
    > Fort Worth, Texas
     
    Newshound, Oct 2, 2006
    #3
  4. Newshound

    Paul Lalli Guest

    Newshound wrote:
    > 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
     
    Paul Lalli, Oct 2, 2006
    #4
  5. Newshound

    -berlin.de Guest

    Newshound <> wrote in comp.lang.perl.misc:
    > 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
     
    -berlin.de, Oct 2, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dpackwood
    Replies:
    3
    Views:
    1,831
  2. pj
    Replies:
    3
    Views:
    300
  3. J M
    Replies:
    2
    Views:
    118
    Tad McClellan
    Nov 6, 2004
  4. Replies:
    20
    Views:
    774
    Gunnar Hjalmarsson
    Jan 18, 2005
  5. Replies:
    4
    Views:
    305
    ccc31807
    Jul 29, 2011
Loading...

Share This Page