App-GitGerrit

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


0.010     2013-10-02 21:10:57 America/Sao_Paulo

  [New Features]
  - Implement 'git gerrit push --norebase' option to avoid rebases
    for brand new change-branches.

  - Make 'git gerrit version' tell the Perl version too.

  [Changes]
  - Use alternative methods to grok credentials for pre-1.8 Gits that
    do not support the git-credential command. Git-gerrit now tries
    alternative methods to grok credentials if it can't grok then via
    git-credential, in this order:
    
    * From the userinfo part of git-gerrit.baseurl.
    * From a .netrc file.
    * Prompting the user.

  - Remove trailing zeroes from dates in 'git gerrit show'.

  - Improve 'git gerrit version' message for pre-2.6 Gerrits.

bin/git-gerrit  view on Meta::CPAN

Git-gerrit takes care of installing this hook for you. When you invoke
its C<new> or C<push> sub-commands, it checks to see if your
repository already has a C<commit-msg> hook installed. If not, it
automatically downloads Gerrit's standard hook and installs it for
you.

=head1 AUTHENTICATION

If you have Git 1.8.0 or later, git-gerrit uses Git's credential
management system via its B<git-credential> command to obtain
credentials for connecting to Gerrit. You can take advantage of this
by configuring Git's C<credential.helper> variable to use a persistent
credential storage and avoid being asked for the authentication
credentials repeatedly. Please, read B<gitcredentials> manpage to know
how to configure this system. But here are a few tips anyway:

=over

=item * B<On Ubuntu Linux (tested on 13.04)>

Use the
L<git-credential-gnome-keyring|http://stackoverflow.com/questions/13385690/how-to-use-git-with-gnome-keyring-integration>
program which provides a very nice integration with your desktop
environment. You have to compile the helper first:

bin/git-gerrit  view on Meta::CPAN

=item * B<On other Unix-like systems>

The B<git-credential-cache> command which comes with Git is as a
balanced compromise between convenience and security:

    git config --global credential.helper cache --timeout 86400

=item * B<On Windows systems>

The best choice seems to be the third-party application
L<git-credential-winstore|http://gitcredentialstore.codeplex.com/>,
which you have to install first.

    git config --global credential.helper winstore

=back

If you're using a pre-1.8 Git that doesn't support the
B<git-credential> command, there are a few fall-backs.

First, git-gerrit tries to get credentials from the
C<git-gerrit.baseurl> configuration variable. The URL should be in a
format like C<https://username:password@host/path>. Security conscious
people should avoid putting credentials there, but if you do
git-gerrit will be satisfied.

Then, git-gerrit tries to load Perl's L<Net::Netrc> module, if
available, to get credentials from a C<netrc(5)> file.

As a last resort, git-gerrit tries to load Perl's L<Term::Prompt>
module to prompt you for the credentials.

If none of this works, git-gerrit dies screaming.

=head1 BASH COMPLETION

If you use bash and have L<bash completion enabled for
Git|http://git-scm.com/book/en/Git-Basics-Tips-and-Tricks> you may
also enable it for git-gerrit by sourcing the
F<etc/bash_completion.d/git-gerrit> script that comes with
L<App::GitGerrit> distribution. You may do it in your F<~/.bashrc>

lib/App/GitGerrit.pm  view on Meta::CPAN

        info "Cannot install $commit_msg hook because you don't have LWP::Simple installed";
    } else {
        info "Installing $commit_msg hook";
        if (LWP::Simple::is_success(LWP::Simple::getstore(config('baseurl') . "/tools/hooks/commit-msg", $commit_msg))) {
            chmod 0755, $commit_msg;
        }
    }
}

# The credential_* routines below use the git-credential command to
# get and set credentials for git commands and also for Gerrit REST
# interactions.

sub url_userinfo {
    my ($url) = @_;
    if (my $userinfo = $url->userinfo) {
        return split /:/, $userinfo, 2;
    } else {
        return (undef, undef);
    }
}

lib/App/GitGerrit.pm  view on Meta::CPAN

        $fh->print("$key=$value\n") if $value;
    }

    $fh->print("\n\n");
    $fh->close();

    return ($fh, $fh->filename);
}

my $git_credential_supported = 1;
sub get_credentials {
    my $baseurl = URI->new(config('baseurl'));
    my ($fh, $credfile) = credential_description_file($baseurl);

    my %credentials;
    debug "Get credentials from git-credential";
    open my $pipe, '-|', "git credential fill <$credfile"
        or error "Can't open pipe to git-credential: $!";
    while (<$pipe>) {
        chomp;
        $credentials{$1} = $2 if /^([^=]+)=(.*)/;
    }
    unless (close $pipe) {
        error "Can't close pipe to git-credential: $!" if $!;

        # If we get here it is because the shell invoked by open
        # above couldn't exec git-credential, which most probably
        # means that we're using a pre-1.8 Git, which doesn't
        # support git-credential yet.
        $git_credential_supported = 0;
    }

    my ($username, $password) = @credentials{qw/username password/};

    unless (defined $username && defined $password) {
        debug "Get credentials from git-gerrit.baseurl";
        ($username, $password) = url_userinfo(config('baseurl'));
    }

    unless (defined $username && defined $password) {
        debug "Get credentials from a .netrc file";
        if (eval {require Net::Netrc}) {
            if (my $mach = Net::Netrc->lookup(URI->new(config('baseurl'))->host, $username)) {
                ($username, $password) = ($mach->login, $mach->password);
            }
        } else {
            debug "Failed to require Net::Netrc";
        }
    }

    unless (defined $username && defined $password) {
        debug "Prompt the user for the credentials";
        if (eval {require Term::Prompt}) {
            $username = Term::Prompt::prompt('x', 'Gerrit username: ', '', $ENV{USER});
            $password = Term::Prompt::prompt('p', 'Gerrit password: ', '');
            print "\n";
        } else {
            debug "Failed to require Term::Prompt";
        }
    }

    defined $username or error "Couldn't get credential's username";
    defined $password or error "Couldn't get credential's password";

    return ($username, $password);
}

sub set_credentials {
    my ($username, $password, $what) = @_;

    return 1 unless $git_credential_supported;

    $what =~ /^(?:approve|reject)$/
        or error "set_credentials \$what argument ($what) must be either 'approve' or 'reject'";

    my $baseurl = URI->new(config('baseurl'));
    my ($fh, $credfile) = credential_description_file($baseurl, $password);

    return system("git credential $what <$credfile") == 0;
}

# The get_message routine returns the message argument to the
# --message option. If the option is not present it invokes the git
# editor to let the user compose a message and returns it.

lib/App/GitGerrit.pm  view on Meta::CPAN

}

# The gerrit routine keeps a cached Gerrit::REST object to which it
# relays REST calls.

sub gerrit {
    my $method = shift;

    state $gerrit;
    unless ($gerrit) {
        my ($username, $password) = get_credentials;
        require Gerrit::REST;
        $gerrit = Gerrit::REST->new(config('baseurl'), $username, $password);
        eval { $gerrit->GET("/projects/" . uri_escape_utf8(config('project'))) };
        if (my $error = $@) {
            set_credentials($username, $password, 'reject') if $error->{code} == 401;
            die $error;
        } else {
            set_credentials($username, $password, 'approve');
        }
    }

    if ($Options{debug}) {
        my ($endpoint, @args) = @_;
        debug "GERRIT->$method($endpoint)";
        if (@args) {
            require Data::Dumper;
            warn Data::Dumper::Dumper(@args);
        }



( run in 0.240 second using v1.01-cache-2.11-cpan-a5abf4f5562 )