#!/usr/bin/env perl
# PODNAME: git-gerrit
# ABSTRACT: Git extension to implement a Gerrit workflow

use utf8;
use 5.010;
use strict;
use warnings;

use Git::Gerrit qw/run/;

return 1 if caller;

exit run();

__END__

=pod

=head1 NAME

git-gerrit - Git extension to implement a Gerrit workflow

=head1 VERSION

version 0.019

=head1 SYNOPSIS

    git gerrit new         [--update] TOPIC [BRANCH]
    git gerrit push        [--keep] [--force] [--[no]rebase] [--draft] [--submit] \
                           [--base BASE] [--topic TOPIC] [--reviewer USER] [--cc USER]

    git gerrit query       [--limit LIMIT] [--verbose] [[NAME=]QUERY]*
    git gerrit my          [--limit LIMIT] [--verbose] [changes|drafts|watched|starred]
    git gerrit show        CHANGE*

    git gerrit checkout    CHANGE*
    git gerrit upstream    [--keep]
    git gerrit cherry-pick OPTIONS* CHANGE

    git gerrit reviewer    [--add USERS] [--confirm] [--delete USERS] [CHANGE]
    git gerrit review      [--message TEXT] [--keep] [[LABEL]=VOTE]* [CHANGE]
    git gerrit abandon     [--message TEXT] [--keep] [CHANGE]
    git gerrit restore     [--message TEXT] [CHANGE]
    git gerrit revert      [--message TEXT] [CHANGE]
    git gerrit submit      [--no-wait-for-merge] [--keep] [CHANGE]

    git gerrit web         [OPTIONS --] CHANGE*

    git gerrit config
    git gerrit version

=head1 DESCRIPTION

Git-gerrit is a Git extension to manage changes using L<Gerrit Code
Review|http://code.google.com/p/gerrit/>.

Git-gerrit offers a rich set of sub-commands to make it easy to
create, query, amend, review, and submit changes to Gerrit, making it
possible to interact with it through the command-line, avoiding its
web interface most of the time and improving your efficiency. The goal
is to make Gerrit's review process feel like a natural extension of
Git.

Git-gerrit provides three main features:

=over

=item * An easy and safe way to push changes to Gerrit through the
B<git gerrit push> sub-command, avoiding the need to type remote names
and long refspecs.

=item * A standard way to map Gerrit changes into local branches,
referred to as "change-branches", making it easier to manage several
changes simultaneously and to perform the fetch-amend-push review
cycle.

=item * Several sub-commands to query and inspect Gerrit changes and
also to review and submit them.

=back

Git-gerrit is implemented on top of L<Gerrit's REST
API|https://gerrit-review.googlesource.com/Documentation/rest-api.html>,
which was consolidated in its version 2.6. As this API matures, expect
git-gerrit to incorporate new functionality.

There are a few alternatives to git-gerrit described L<below|/"SEE ALSO">.

=encoding utf8

=head1 GLOSSARY

There are a few concepts that should be clear in order to the
sub-commands documentation below to make sense.

=over

=item B<change>

Each commit pushed to one of Gerrit's virtual branches (C<refs/for> or
C<refs/drafts>) creates a C<change> for review.

=item B<Change-Id>

A
L<Change-Id|https://gerrit-review.googlesource.com/Documentation/user-changeid.html>
is a 40-hexadecimal characters long SHA-1 hash prefixed with an
C<I>. It uniquely identifies a change and is normally generated by the
C<commit-msg> hook and inserted in the commit message footer.

=item B<{change-id}>

A
L<{change-id}|https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-id>,
is a more general identifier used by Gerrit's REST API to uniquely
identify a change . It can be expressed in one of three forms:

=over

=item * As an ID of the change in the format
"<project>~<branch>~<Change-Id>", where, for the branch, the
C<refs/heads/> prefix can be omitted (e.g.,
C<myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940>).

=item * As a C<Change-Id> if it uniquely identifies one change
(e.g., C<I8473b95934b5732ac55d26311a706c9c2bde9940>).

=item * As a legacy numeric change ID (e.g., C<4247>).

=back

You may pass any form of change-id to git-gerrit's sub-commands when
they require a CHANGE argument. Most commonly, you'll be using the
legacy numeric ID, just because it's more convenient.

=item B<upstream branch>

You normally should avoid creating changes directly on a local
tracking branch. Instead, you should create a local topic branch
deriving from the tracking branch to work on each change. We refer to
the tracking branch from which your topic branch derived as the
topic's C<upstream branch>.

=item B<change-branch>

A C<change-branch> is a local branch with a special name that
git-gerrit creates and maps to a Gerrit change.

When the sub-command C<git gerrit new TOPIC BRANCH> starts a new
change it creates a topic branch named B<change/BRANCH/TOPIC>, which
we call a change-branch. We refer to BRANCH as the change-branch's
C<upstream>, because it is the branch from which the change-branch
derives and to which it will be ultimately merged back again.

When C<git gerrit checkout CHANGE> fetches an existing change it
creates a change-branch named B<change/BRANCH/ID>, where BRANCH is the
name of the branch associated with the change, and ID is its legacy
numeric change ID.

So, you should reserve the C<change/> top-level branch name for the
change-branches managed by git-gerrit.

=back

=head1 WORKFLOW

Here are the main use-cases of git-gerrit to manage your changes.

=head2 Creating a new change for review

Suppose you want to create a new change on master:

    git gerrit new topic master
    # edit
    git commit
    git gerrit push

First you create a new change-branch for your new change. If you're
already in master you don't need to mention it on the first line. Then
you make your change editing your working area and committing. When
you're done, simply tell git-gerrit to push your change and get back
to master.

In order to do the same thing using only standard Git commands you'd
do something like this:

    git checkout master
    git pull --ff-only
    git checkout -b change/master/topic
    # edit
    git commit
    git push origin HEAD:refs/for/master
    git checkout master
    git branch -D change/master/topic

=head2 Reviewing a change

    git gerrit my changes
    git gerrit checkout 1234
    git show
    git gerrit review =-1

First, if you don't know the C<{change-id}> of the change you want to
review, you ask C<my changes> to get a list of the changes still
unreviewed. Then you checkout one change and study it. Finally, you
record your review and gets back to the change's upstream branch.

Without git-gerrit you'd have to perform the review using Gerrit's web
interface.

=head2 Amending a change

    git gerrit checkout 1234
    # edit
    git commit --amend
    git gerrit push

To amend a change you first check it out to a local
change-branch. Then you can amend it and, finally, push it as another
patch-set to Gerrit, checking out upstream again.

What if you want to make a comment on your new patchset? No problem,
simply change the last line above for this:

    git gerrit push --keep && git gerrit review

Without git-gerrit you would have to go first to Gerrit's web
interface, find the change, and copy its fetch/checkout command
line. Then you could paste it in your terminal and perform the
amending like this:

    git fetch https://gustavo@gerrit.example.net/project refs/changes/90/1190/2 && git checkout FETCH_HEAD
    # edit
    git commit --amend
    git push origin HEAD:refs/for/master
    git checkout master

Oh, and if you want to comment on the new patchset, you have to go to
Gerrit's web interface again.

=head1 SUB-COMMANDS

Each git-gerrit sub-command has its own set of options, described in
its own section below.

The options below, however, are accepted by all of them:

=over

=item B<--debug>

This option makes git-gerrit print to STDERR every system command
(usually a Git command) invoked and every Gerrit REST call made during
the execution of its sub-commands. System commands are prefixed with
B<CMD:> and Gerrit REST calls with B<GERRIT:>.

=item B<--help>

Shows git-gerrit's manpage and quits.

=back

Options names may be abbreviated to uniqueness, case does not matter,
and a single dash is sufficient, even for long option names.

=head2 git gerrit new [--update] TOPIC [BRANCH]

The C<new> sub-command creates a new change-branch off of BRANCH
called C<change/BRANCH/TOPIC> and checks it out for you to start
making changes to your working area.

If no BRANCH is specified, the new change is based on the current
branch, unless it's a change-branch itself, in which case the new
change is based on the current change-branch's upstream branch.

The TOPIC name must contain at least one non-digit character so that
it's clear that this is a new change-branch, not yet pushed to
Gerrit. Also, the TOPIC name cannot contain slashes so that it's not
confused with the branch name. It's usually best to use only letters
and hyphens.

=over

=item B<--update>

This option makes git-gerrit update BRANCH before creating the
change-branch by fetching from Gerrit and fast-forward-merging it with
its remote branch. This way you guarantee to start a change on top of
the newest state of your project, which is usually the right thing to do.

=back

You will be warned if your working area is dirty, as this is sometimes
a mistake.

=head2 git gerrit push OPTIONS*

The C<push> sub-command should be invoked to push a change-branch to
Gerrit's C<refs/for/> branch associated with its upstream branch. It
should be invoked when you have the change-branch checked out in your
working area.

When a new change-branch is pushed it creates a Gerrit change
associated with the TOPIC in its name, as created by C<git gerrit new>
above.

After a successful push, git-gerrit checks out the upstream branch and
deletes the original change-branch. The goal is to maintain a clean
namespace, containing only the change-branches that are being worked
on. When you push one to Gerrit, you don't need to keep it any longer
locally. If you need to amend it later, you'll be able to get to it
with the C<git gerrit checkout> sub-command.

=over

=item B<--keep>

This option tells git-gerrit not to checkout the upstream and not to
delete the change-branch, keeping your working area intact.

=item B<--force>

By default, git-gerrit refuses to push a change-branch unless it
contains a single commit dangling from its upstream and git status is
clean (i.e., C<git status --untracked-files=no> doesn't show any
modification that hasn't been added to the index). If either one of
these conditions don't hold it dies with an error message telling
what's the problem. If you're sure you want to push anyway, you can
use this option. If both conditions don't hold, you'll have to use the
option twice.

It's best to avoid multiple commit pushes, because if you have to
amend them later, having multiple commits may require rebasing
dependent commits, which is a more complex operation and clutters the
review history of the change.

If git status isn't clean, the change-branch isn't rebased and the
upstream isn't checked out.

=item B<--[no]rebase>

Before a brand new change-branch (one ending in a TOPIC C<name>) is
pushed, its upstream branch is updated and it is rebased on top of its
upstream. This is to make sure you're pushing a change based on the
newest project state. If, by any reason, you don't want to have it
rebased, use the C<--norebase> option.

A change-branch that has been checked out (one ending in an ID) 't
rebased by default, because this would clutter the change review
history in Gerrit. If you want it rebased nonetheless, use the
C<--rebase> option.

=item B<--draft>

This option makes git-gerrit push the change-branch to
C<refs/drafts/UPSTREAM> instead of to C<refs/for/UPSTREAM>, creating a
draft change in Gerrit.

=item B<--submit>

This option tells Gerrit to L<auto-merge the change during
push|http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/user-upload.html#auto_merge>,
which is a feature implemented in Gerrit 2.7.

=item B<--base BASE>

This option L<selects a new merge
base|http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/user-upload.html#base>
for Gerrit, which is a feature implemented in Gerrit 2.7.

=item B<--topic TOPIC>

This option specifies another name for the topic that will be
associated with the change. By default, the topic name is the last
component of the current change-branch name, as specified by the C<git
gerrit new> sub-command.

=item B<--reviewer USERS>

This option let's you invite a list of users to review your change.

USERS is a colon-separated list of usernames. You may also pass this
option more than once, to invite more than a set of users.

=item B<--cc USERS>

This option let's you notify a list of users about your change.

USERS is a colon-separated list of usernames. You may also pass this
option more than once, to invite more than a set of users.

=back

=head2 git gerrit query [--limit LIMIT] [--verbose] [[NAME=]QUERY]*

The B<query> sub-command let's you list Gerrit changes meeting
specific criteria. The matching changes are shown in tabular format,
one change per line, listing their legacy ID, status, Code-Review
vote, time of last update, project name, branch name, owner name, and
subject line.

You may pass a list of queries. Each QUERY's results is presented
separated from the other by a empty line and a header containing the
query's name and expression inside brackets. For example:

    $ git gerrit query 'Starred changes=is:starred' is:draft

    [Starred changes=is:starred]
    ID    STATUS CR UPDATED    PROJECT    BRANCH OWNER          SUBJECT
    1186  MERGED +2 2013-09-18 helloworld master Gustavo Chaves [SB-1] Test amend 3

    [QUERY=is:draft]
    ID    STATUS CR UPDATED    PROJECT    BRANCH OWNER          SUBJECT
    1187  NEW       2013-09-08 helloworld master Gustavo Chaves [SB-2] Make foo

Note that unnamed queries are prefixed by C<QUERY=> instead of by their names.

Each QUERY can be specified by a L<Gerrit search
expression|https://gerrit-review.googlesource.com/Documentation/user-search.html>.

=over

=item B<--limit LIMIT>

This option put a limit on the number of changes that are shown for
each QUERY.

=item B<--verbose>

This option makes the change topic be shown inside parenthesis to the
right of the change branch name. This requires a separate REST call
for each change, making the result appear more slowly.

=back

=head2 git gerrit my [--limit LIMIT] [--verbose] [changes|drafts|watched|starred]

The B<my> sub-command provides a set of pre-defined queries for the
B<query> sub-command. It's based on Gerrit's standard queries shown in
its web interface under the C<My> tab.

The C<changes> argument is used by default if you don't specify any.

The options taken by the C<my> sub-command are passed to the C<query>
sub-command.

=head2 git gerrit show CHANGE*

The B<show> sub-command describes one or more CHANGEs in detail,
showing much like what Gerrit shows in a change page of its web
interface. For example:

    $ git gerrit show 1186
     Change-Num: 1186
      Change-Id: I0bb976fe1890657d7a1c3ba403e0b58ac2b63cd7
        Subject: [SB-1] Test amend 3
          Owner: Gustavo Chaves
        Project: helloworld
         Branch: master
        Created: 2013-09-18 16:22:21
        Updated: 2013-09-18 19:45:56
         Status: MERGED

    REVIEWER                         Code-Review
    Gustavo Leite de Mendonça Chaves  0
    Jenkins                          +1
    Laurel Keys                      +2
    ------------------------------------------------------------

If no CHANGE is specified, the one associated with the current
change-branch is described. If you're not in a change-branch, you'll
get an error.

=head2 git gerrit checkout CHANGE*

The B<checkout> sub-command fetches one or more CHANGEs from Gerrit,
creates change-branches pointing to them and checks out the last one.

A Gerrit change may contain a series of patch-sets. The C<checkout>
fetches the current (latest) one. If there is already a change-branch
for the change, it will be updated to the change's current patch-set.

If you omit the CHANGE argument and you are in a change-branch, it will
be updated with its current patch-set.

The shorter name C<co> can also be used instead of C<checkout>.

=head2 git gerrit upstream [--keep] [--delete]

The B<upstream> sub-command should be invoked when you're in a
change-branch. It checks out the upstream branch and deletes the
change-branch if it's associated with an already pushed change, i.e.,
if its name ends in a legacy numeric id, not in a topic name.

The shorter name C<up> can also be used instead of C<upstream>.

=over

=item B<--keep>

This option prevents the change-branch deletion after the upstream
checkout.

=item B<--delete>

This options forces the change-branch deletion when it's a new
change. However, the <--keep> option has precedence, meaning that if
both options are present the change-branch isn't deleted.

=back

=head2 git gerrit cherry-pick OPTIONS* CHANGE

The B<cherry-pick> sub-command fetches CHANGE from Gerrit and applies
it to the current branch using the C<git cherry-pick> command. The
CHANGE id is required and every OPTION (but --debug) is passed as-is
to the C<git cherry-pick> command. You should read B<git-cherry-pick>
manpage to know what options are available. Some of the most usefull
ones are these: B<-e>, B<-x>, and B<-n>.

The shorter name C<cp> can also be used instead of C<cherry-pick>.

=head2 git gerrit reviewer [--add USERS] [--confirm] [--delete USERS] [CHANGE]

The B<reviewer> sub-command allows you to manage the list of reviewers
for a CHANGE. You can omit the CHANGE argument if you're in a
change-branch. In this case, you'll be managing the associated change
reviewers.

=over

=item B<--add USERS>

This option let's you invite new users to review the change. You can
pass a comma-separated list of users and even use more than one
C<--add> option.

You can use Gerrit groupnames in addition to usernames, if you want to
invite a group of users to review.

=item B<--confirm>

Gerrit may reject the addition of groups with too many users because
it recons you may be doing it by mistake. In this case, you'll receive
an error message something like this:

    "The group My Group has 15 members. Do you want to add them all as reviewers?"

If you really want to invite them all, try again with using the
C<--confirm> option.

=item B<--delete USERS>

This option let's you remove reviewers from the change. You can pass a
comma-separated list of users and even use more than one C<--delete>
option.

You can use Gerrit groupnames in addition to usernames, if you want to
remove a group of reviewers.

=back

After adding and removing reviewers, C<git gerrit reviewers> shows the
remaining list of reviewers of the CHANGE.

=head2 git gerrit review [--message TEXT] [--keep] [[LABEL]=VOTE]* [CHANGE]

The B<review> sub-command allows you to review (duh!) a CHANGE by
casting votes and adding messages to it.

You can omit the CHANGE argument if you are in a change-branch, in
which case you'll be reviewing the associated change. In this case,
after a successful review, the change-branch will be deleted and its
upstream checked out.

You can cast multiple votes using C<LABEL=VOTE> arguments, where LABEL
names a Gerrit
L<label|https://gerrit-review.googlesource.com/Documentation/config-labels.html>
and VOTE is a negative, zero, or positive number. If you omit the
LABEL name (but not the equal sign!) you'll be voting in the standard
C<Code-Review> label.

The Git editor (see the definition of C<GIT_EDITOR> with the C<git
help var> command) is invoked for you to compose a message to be added
to the review.

=over

=item B<--message TEXT>

This option adds a message to the review avoiding the Git editor
invocation.

=item B<--keep>

This option avoids the change-branch deletion after a successful review.

=back

=head2 git gerrit submit [--no-wait-for-merge] [--keep] [CHANGE]

The B<submit> sub-command submits an approved CHANGE, making Gerrit
merge it into its remote upstream branch.

You can omit the CHANGE argument if you are in a change-branch, in
which case you'll be submitting the associated change. In this case,
after a successful submission, the change-branch will be deleted and
its upstream checked out.

=over

=item B<--no-wait-for-merge>

By default git-gerrit will wait for the merge of the change into its
branch to complete in Gerrit. This option tells it not to wait and
finish as soon as it receives Gerrit's submit acknowledge.

=item B<--keep>

This option avoids the change-branch deletion after a successful
submission.

=back

=head2 git gerrit abandon [--message TEXT] [--keep] [CHANGE]

The B<abandon> sub-command abandons an unmerged CHANGE.

You can omit the CHANGE argument if you are in a change-branch, in
which case you'll be abandoning the associated change. In this case,
after a successful abandonment, the change-branch will be deleted and
its upstream checked out.

The Git editor (see the definition of C<GIT_EDITOR> with the C<git
help var> command) is invoked for you to compose a message to be added
to the action.

=over

=item B<--message TEXT>

This option adds a message to the review avoiding the Git editor
invocation.

=back

=over

=item B<--keep>

This option avoids the change-branch deletion after a successful
abandonment.

=back

=head2 git gerrit restore [--message TEXT] [CHANGE]

The B<restore> sub-command restores an abandoned CHANGE.

You can omit the CHANGE argument if you are in a change-branch, in
which case you'll be restoring the associated change.

The Git editor (see the definition of C<GIT_EDITOR> with the C<git
help var> command) is invoked for you to compose a message to be added
to the action.

=over

=item B<--message TEXT>

This option adds a message to the review avoiding the Git editor
invocation.

=back

=head2 git gerrit revert [--message TEXT] [CHANGE]

The B<revert> sub-command reverts an already merged CHANGE. Gerrit
does so by creating, in the server, a new change with an inverted
patch on top of the CHANGE remote upstream branch.

You can omit the CHANGE argument if you are in a change-branch, in
which case you'll be reverting the associated change.

The Git editor (see the definition of C<GIT_EDITOR> with the C<git
help var> command) is invoked for you to compose a message to be added
to the action.

=over

=item B<--message TEXT>

This option adds a message to the review avoiding the Git editor
invocation.

=back

=head2 git gerrit web [OPTIONS --] CHANGE*

The B<web> sub-command opens up in your browser Gerrit's web page for
each CHANGE. It does it by invoking C<git web--browse> for the list of
URLs associated with each CHANGE. If no CHANGE is specified and you
are in a change-branch, the page associated with the current CHANGE is
openned.

Every option (but --debug) is passed as-is to the C<git web--browse>
command. If you pass any option you must mark the end of them with a
'--' mark.

=head2 git gerrit config

The B<config> sub-command lists Git's configuration variables in the
C<git-gerrit> section. The variables C<remote>, C<baseurl>, and
C<project> are always shown, even if they're inferred and not
explicitly configured.

=head2 git gerrit version

The B<version> sub-command shows the versions of git-gerrit, Git, and
Gerrit that you're using.

=head1 INSTALLATION

Git-gerrit requires Perl 5.10 or newer and Git (any version should do,
but 1.8 is better integrated). Check it like this:

    perl -v
    git --version

Git-gerrit is part of the
L<Git::Gerrit|http://search.cpan.org/dist/Git::Gerrit/>
distribution that you have to download from
L<CPAN|http://search.cpan.org/> and install. There are a few ways to
do it, depending on your environment. Here are a few tips:

=head2 If you cook your own Perl

If you build your own Perl, perhaps using
L<perlbrew|http://perlbrew.pl/>, you know the drill:

    cpanm Git::Gerrit

=head2 Debian, Ubuntu, etc.

If you want to use the Perl that comes packaged in your Debian-based
distribution, you can install some git-gerrit dependencies from
packaged perl modules. These are the ones packaged with Ubuntu 12.04:

    sudo apt-get install -y \
        liburi-encode-perl libhtml-tree-perl libjson-perl \
        libscope-guard-perl libcrypt-ssleay-perl libwww-perl cpanminus

The nifty C<cpanm> installer should take care of the remaining
dependencies and of installing C<git-gerrit> for you like this:

    sudo su -l -c "cpanm Git::Gerrit"

=head2 RedHat, CentOS, etc.

If you want to use the Perl that comes packaged in your RedHat-derived
distribution, you can install some git-gerrit dependencies from
packaged perl modules. These are the ones packaged with CentOS 6.4:

    sudo yum install -y \
        perl-URI perl-HTML-Tree perl-JSON perl-Scope-Guard \
        perl-Test-Exception perl-Test-use-ok perl-Crypt-SSLeay perl-YAML \
        perl-CPAN perl-ExtUtils-MakeMaker

The verbose C<cpan> installer should take care of the remaining
dependencies and of installing C<git-gerrit> for you like this:

    sudo su -l -c "cpan Git::Gerrit"

=head2 Windows

On Windows I suggest that you install L<Strawberry
Perl|http://strawberryperl.com/>. Then, open a command line tool and
type this:

    cpanm Data::Util Git::Gerrit

Note that on Windows you may have to invoke C<git-gerrit> directly as
B<git-gerrit> and not through Git as B<git gerrit>. This is because
Git will probably use the old Perl that comes bundled with it, not
Strawberry Perl. Your mileage may vary, though.

=head1 CONFIGURATION

Git-gerrit is configured through Git's standard configuration
framework, which you can read about with the C<git help config>
command. All git-gerrit's configuration variables are in the
C<git-gerrit> section and can be created at the C<system>, the
C<global>, or the C<local> level. More specifically, git-gerrit groks
its configuration from the output of the C<git config -l> command.

=head2 Git and Gerrit access

In order to interact with Gerrit, git-gerrit has to know three things
which it can usually infer from your default Git configuration, but
that you may be explicit about using these Git configuration
variables:

=over

=item * B<git-gerrit.remote>

Whenever git-gerrit invokes a Git command to interact with Gerrit
(e.g., git-push and git-fetch) it refers to Gerrit using a remote
name. You probably already have a remote configured for Gerrit. If you
don't, git-gerrit assumes the name C<origin> by default.

You can check your Git remotes by issuing the command C<git remote
-v>. Note that the remote's URL must use the HTTP or (better yet)
HTTPS protocol, not SSH.

=item * B<git-gerrit.baseurl>

This is the value of the
L<gerrit.canonicalWebUrl|https://gerrit-review.googlesource.com/Documentation/config-gerrit.html#_a_id_gerrit_a_section_gerrit>
variable configured in the C<etc/gerrit.config> file at Gerrit's
server. It's needed so that git-gerrit can interact with Gerrit's REST
API.

If you don't specify it, git-gerrit assumes that it is equal to the
remote's URL minus the path.

This usually can be configured globally, if you have a Gerrit server
hosting several of your repositories.

It's a good idea to have your username in this URL to avoid being
asked for it interactively.

=item * B<git-gerrit.project>

This is the name of the project associated with the Gerrit
repository. It's needed so that git-gerrit can interact with Gerrit's
REST API.

If you don't specify it, git-gerrit assumes that it is equal to the
path of the remote's URL stripped of any path in
C<git-gerrit.baseurl>.

=back

This is designed so that for most Gerrit instances git-gerrit should
work out of the box, without any explicit configuration.

For example, if you're working on Android's
L<kernel|https://android-review.googlesource.com/#/admin/projects/kernel/common>
project, you may clone it with the suggested command:

    git clone https://android.googlesource.com/kernel/common

Then, git-gerrit will figure this out from the clone URL:

    git-gerrit.remote = origin
    git-gerrit.baseurl = https://android.googlesource.com
    git-gerrit.project = kernel/common

If you're working on Eclipse's
L<egit|https://git.eclipse.org/r/#/admin/projects/egit/egit> project,
however, you must help git-gerrit figuring its configuration. This is
the suggested command to clone it:

    git clone https://git.eclipse.org/r/egit/egit

Note that the base URL has a path part (C</r>). So, in this case you
must configure it explicitly like this:

    git config --global git-gerrit.baseurl https://git.eclipse.org/r

The remote and the project names can be inferred automatically.

=head2 Option defaults

Each git-gerrit sub-command accept a specific set of options and each
option has a default value which is specified in the sub-commands
documentation. You can specify a default set of options for each
sub-command by defining a variable like this:

=over

=item * B<options.COMMAND> OPTIONS

OPTIONS is the option list that should be passed as default for
COMMAND. Specifically, it's a string which is split on spaces and the
resulting list is unshifted on @ARGV, so that it's like you have
passed these options on the command line first.

So, for example, if you'd like to always update the upstream branch
when you create a new change-branch, you can pass the C<--update>
option to C<new> by default by setting this:

    git config git-gerrit.options.new --update

Options common to all commands can be specified to the pseudo-command
'all' like this:

    git config git-gerrit.options.all --debug

=back

=head2 Automatic reviewers

You can tell git-gerrit to invite automatically some users to review
your pushed changes based on their upstream branch name and on the
files affected.

=over

=item * B<git-gerrit.reviewers USERS [CONDITION]*>

This variable specifies a list of Gerrit users to be automatically
invited as reviewers in a B<git gerrit push> command.

USERS is a colon-separated list of usernames.

CONDITIONs are space-separated boolean expressions. All CONDITIONs, if
any, must be true for USERS to be invited. If no CONDITIONS are
specified, USERS are invited.

A CONDITION may check either the name of the branch to which the
change is being pushed or the names of the files affected by the
change itself. The matching may be either exact or by L<regular
expressions|perlre>, as follows.

=over

=item * branch=REFNAME

Checks if REFNAME is exactly equal to the change's upstream name
(without the C<refs/heads> prefix).

=item * branch~REGEXP

Checks if the upstream name matches REGEXP.

=item * path=PATH

Checks if the path of any file affected by the commit being pushed, as
shown by C<git diff --name-only upstream..HEAD> is exactly equal to
the complete path of one of those files.

=item * path~REGEXP

Checks if the path of any affected file matches REGEXP.

=back

You may specify the C<git-gerrit.reviewers> variable multiple
times. All users mentioned in all specifications that match their
CONDITIONs are invited as reviewers to the current change being
pushed.

=back

=head1 COMMIT-MSG HOOK

Gerrit provides a C<commit-msg> hook for Git that should be installed
in your repositories. Its purpose is to insert a C<Change-Id> footer
in the commit messages so that Gerrit can discern independent commits
from merely amended ones.

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:

    sudo apt-get install libgnome-keyring-dev
    sudo make -C /usr/share/doc/git/contrib/credential/gnome-keyring
    git config --global credential.helper /usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring

=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<Git::Gerrit> distribution. You may do it in your F<~/.bashrc> file
like this:

    source $PERL_ROOT/etc/bash_completion.d/git-gerrit

Where C<PERL_ROOT> is the root of your Perl installation.

=head1 SEE ALSO

There are some alternatives to git-gerrit, other Git extensions to
make it easier to interact with Gerrit. The three mentioned below are
the most well known. All of them use Gerrit's mature and simple SSH
API while git-gerrit's distinguishes from them in that it uses
Gerrit's newer and more comprehensive REST API.

=over

=item * L<git-review|https://github.com/openstack-infra/git-review>

Being the original inspiration for git-gerrit, git-review is a mature
tool that's used by some very well known projects, such as OpenStack,
MediaWiki, and LibreOffice.

=item * L<git-change|https://github.com/Nextdoor/git-change>

Simpler than git-review, git-change is better documented and has the
best name of all. From it, git-gerrit took the change-branch concept.

=item * L<querrit|https://gitorious.org/querrit/querrit>

A very simple tool to query Gerrit and make it easier to push changes.

=back

If you're interested in Gerrit automation per se, you can take a look
at the L<Gerrit::REST> Perl module, which is used by C<git-gerrit> to
interact with Gerrit via it's REST API.

=head1 AUTHOR

Gustavo L. de M. Chaves <gnustavo@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by CPqD <www.cpqd.com.br>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
