1
votes

I'm trying to execute a git command from perl via IPC::Run which catches STDOUT/STDERR-Output from git in perl variables.

Here is what i did:

use strict;
use warnings;
use IPC::Run;
my $stderr, $stdout, @cmd;
push @cmd, "git";
push @cmd, "clone";
push @cmd, "http://my.gitserver.com/scm/tst2/abc.git";

my $success = IPC::Run::run \@cmd, '>', \$stdout, '2>', \$stderr;
1;

Running this results in:

  • $stdout: Cloning into 'abc'...
  • $stderr: EMPTY

Running git command from commandline directly results in following output:

$ git clone http://my.gitserver.com/scm/tst2/abc.git
Cloning into 'abc'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.

As you can see, git produces some more output on commandline than I actually capture within my perl implementation.

What's going wrong?

1
did you check the $stderr variable? also, when I have to manage a GIT repository from perl, I use the Git::Repository module.Miguel Prz
The extra output might only be provided when STDOUT is connected toa terminal. If so, providing a pseudo TTY might should convince git to output it. Note that it will surely contain many terminal control characters (carriage returns and backspaces).ikegami
@miguel-prz:As I said, $stderr is empty after my call ... Using Git::Repository module is not easily usable in my case (as my "server" gets the command to execute from a remote machine and writes the result to a shared sandbox - the received commands can be "anything" - not only git commands ... @ikegami: Have no idea yet how to do this ...hoppfrosch
What happens when you use Run3 instead of Run? ie: Run3(\@cmd,\$stdin,\$stdout,\$stderr);Myforwik

1 Answers

3
votes

The good news is your code is correct. The confusing part is git changes its output depending on whether the standard error is connected to a terminal.

To reproduce your Perl program’s output from a shell, run the following command from a bash prompt.

$ git clone http://my.gitserver.com/scm/tst2/abc.git |& cat
Cloning into 'abc'...

The |& redirection connect the git’s standard error (where the expected progress output goes) and standard output to a pipe rather than the terminal.

To see the usual output, you will have to connect git’s standard error to a pseudo terminal, also known as a pty. IPC::Run has support for pseudo terminals, described in the Pseudo Terminals section of its documentation. Instead of redirecting standard error with 2>, use 2>pty> instead. Note that this adds a dependency to IO::Pty.

Tweaking the run redirect and adding debug output as in the code below

#! /usr/bin/env perl

use strict;
use warnings;

use IPC::Run;

my $cloneurl = 'http://my.gitserver.com/scm/tst2/abc.git';

my($stderr,$stdout);
my @cmd = (qw/ git clone /, $cloneurl);

my $success = IPC::Run::run \@cmd, '>', \$stdout, '2>pty>', \$stderr;
print "success=[$success]\n";
print "stdout=[$stdout]\n";
print "stderr=[$stderr]\n";

produces output that resembles

success=[1]
stdout=[]
stderr=[Cloning into 'abc'...
remote: Counting objects: 2818, done.
remote: Compressing objects: 100% (1965/1965), done.
remote: Total 2818 (delta 1200), reused 770 (delta 287)
Receiving objects: 100% (2818/2818), 2.19 MiB | 1.19 MiB/s, done.
Resolving deltas: 100% (1200/1200), done.
Checking connectivity... done.
]