.. _post-review:
.. program:: post-review

===========
post-review
===========

Overview
========

:command:`post-review` is a command line tool for Windows, Linux and MacOS X
that simplifies both creating and updating review requests. It can look at
your source directory, generate a diff, and upload it to a new or existing
review request on an associated Review Board server. This saves a lot of time
over the web UI, and for some types of code repositories (such as Perforce),
it's actually required in order to produce a compatible diff.


Installation
============

:command:`post-review` is part of the RBTools package.

Before installing RBTools, you will need to have both Python and Setuptools
installed.

We require Python 2.x. We recommend installing Python 2.7. The 3.x releases
will not work.


Installing Python
-----------------

Linux
~~~~~

Python 2.x should come with your distribution. If not, or if 2.x isn't
installed, you will need to install the appropriate package. Please refer to
your package manager for the appropriate version.


Windows
~~~~~~~

You can install Python by running the latest `Python 2.7 Installer`_ for
Windows. We recommend the 32-bit MSI installer, as Setuptools is not packaged
for 64-bit.

.. _`Python 2.7 Installer`: http://www.python.org/download/releases/2.7.3/


Installing Setuptools
---------------------

Linux
~~~~~

To install Setuptools on Debian_, Ubuntu_, or another Debian-based
distribution, type::

    $ apt-get install python-setuptools


To install on Fedora_ 8 and above, type::

    $ yum install -y python-setuptools-devel.noarch

To install on a `RedHat Enterprise`_, CentOS_, Fedora_ 7 and earlier, or
another RedHat-based distribution, type::

    $ yum install python-setuptools


Users of other distributions should check with their distribution for native
packages, or follow the `setuptools installation`_ instructions.

If the version of setuptools available for your distribution is older than
0.6c9, you'll need to install it first, and then upgrade it to the latest
version by running::

    $ easy_install -U setuptools


.. _`Python setuptools`: http://peak.telecommunity.com/DevCenter/setuptools
.. _`setuptools installation`: http://peak.telecommunity.com/DevCenter/EasyInstall#installation-instructions


Windows
~~~~~~~

You'll then need to run the latest `Python Setuptools Installer`_ (look
toward the bottom of the page for the file listing).

Once Python and Setuptools are installed, you may need to add a couple
directories to your system path.

1. Open :menuselection:`Start --> Control Panel` and navigate to the
   :guilabel:`System` icon.
2. Click on the :guilabel:`Advanced` tab.
3. Click :guilabel:`Environment Variables`.
4. Find :envvar:`PATH` in :guilabel:`System variables` and click
   :guilabel:`Edit`.
5. Add ``;C:\Python27;C:\Python27\Scripts`` (substitute your Python
   directory if it's not ``C:\Python27``) to the end of the list.

.. _`Python Setuptools Installer`: http://pypi.python.org/pypi/setuptools#windows


Installing RBTools
------------------

Once Python and Setuptools are installed, you can install RBTools just by
typing::

    $ easy_install -U RBTools


.. _Debian: http://www.debian.org/
.. _Ubuntu: http://www.ubuntu.com/
.. _`RedHat Enterprise`: http://www.redhat.com/
.. _Fedora: http://fedoraproject.org/
.. _CentOS: http://www.centos.org/


Posting and Updating Review Requests
====================================

Depending on the repository type, :command:`post-review` will either require
a changeset number, or it will rely on the changes in the current source
tree. The end result is that :command:`post-review` will build a diff and
post it to a Review Board server. The diff and any additional review
request information will be saved on the server as a draft, which can then
be published.

After posting a new review request or updating an existing one,
:command:`post-review` will display the URL of the review request.
If the :option:`-o` parameter is passed, a browser will be opened to
that URL.

The following subsections will explain how :command:`post-review` is used
with different repository types.


Perforce
--------

Posting Changesets
~~~~~~~~~~~~~~~~~~

Perforce has a concept of changesets, which are server-stored descriptions of
a change along with an ID number and associated files. For Perforce, Review
Board stores changeset numbers of a posted change and can use these to
associate particular changes with review requests.

To post a review request for a specific change, or to update an existing
review request for that change, type::

    $ post-review CHANGENUM

Where ``CHANGENUM`` is the changeset number in Perforce.

The diff will be generated and uploaded to Review Board, and the review
request information will be updated based on the changeset description.

:command:`post-review` must be used if you're using Perforce with
Review Board, as the diff generated by :command:`p4 diff` doesn't provide
the information necessary to properly display a side-by-side diff.


Posting Paths
~~~~~~~~~~~~~

There are cases where you may want to post individual paths containing files
instead of changesets. Take the following cases, for example:

* You have code or other files that must be checked in before they're
  reviewed and have undergone multiple changes.
* You're working in a side branch for a while, possibly with other people,
  and need to review the code before it's integrated into the main branch.
* You want to post a really old, previously abandoned change for review
  that previously went unreviewed.

To post with a path, :command:`post-review` should be run with a standard
Perforce depot path as a parameter, which may contain revision information.
The following paths are supported:


**Uploading a file as a "new" file**::

   //path/to/file

**Uploading all files in a directory as "new" files**::

   //path/to/dir/...

**Uploading a file from a revision as a "new" file (not as common)**::

   //path/to/file/[@#]rev

**Uploading a diff of a file between two revisions**::

   //path/to/file[@#]rev,[@#]rev

**Uploading a diff of all files between two revisions in a directory**::

   //path/to/dir/...[#@]rev,[#@]rev


CVS and Subversion
------------------

CVS and Subversion don't have a concept of changesets, so instead the
working copy's uncommitted changes are posted for review. To post a
review request with all uncommitted files in a tree, simply run::

    $ post-review

This will create a new review request and post the diff of the uncommitted
changes. If you instead want to update an existing review request with
new changes, use the :option:`-r` parameter. For example, to update
review request #42, type::

    $ post-review -r 42

If you need to post specific files, leaving other uncommitted files out of
the review request, you can include them on the command line, like so::

    $ post-review src/foo.c data/bar.png


.. _DVCS:

Distributed Version Control Systems
-----------------------------------

If you're using a distributed version control system, such as Git or
Mercurial, then you may be working on code based on a branch that isn't
available to the repository Review Board has configured. In these cases,
you'll want to take advantage of :command:`post-review`'s parent diff
support.

.. index:: parent diffs

A parent diff is a diff between some known upstream revision that Review Board
has access to and the parent of your branch. It's used to provide a working
baseline for your branch's diff.

For example, in the case of Git, you may be working on the ``topicB`` branch,
which has an ancestry that looks like::

   o master
    \
     o---o topicA
          \
           o---o topicB

If you want to upload a diff of everything between ``topicA`` and ``topicB``,
you would need to tell :command:`post-review` to generate a parent diff
between ``master`` and ``topicA``.

This is done by using the :option:`--parent` parameter with the branch name.
For example, in this case you would simply do::

    $ post-review --parent=topicA

That would generate a parent diff between ``master`` and ``topicA``, and
a normal diff of your changes between ``topicA`` and ``topicB``. The changes
in the parent diff won't appear as changed lines in the diff viewer, meaning
that users will only see changes made on ``topicB``.


Tracking Branches
~~~~~~~~~~~~~~~~~

When using Git, post-review makes the assumption that the closest upstream
branch for the diff will be ``origin/master``. This may be wrong if you
are working on a feature branch or have a remote named something other than
``origin``.

In this case, you will want to use the :option:`--tracking-branch` option,
which specifies the remote branch name. For example::

    $ post-review --tracking-branch=upstream/master


ClearCase
---------

:command:`post-review` provides basic support for posting ClearCase reviews.
If you want to post a review of all currently checked out files in your view
simply run::

     post-review

If you collect changesets, for example, using ClearCase/ClearQuest
integration, you can pass the changeset using :option:`--revision-range`.
Repository will be determined based on your current VOB's uuid or name::

    $ post-review --revision-range="/vobs/proj/file.c@@/main/0:/vobs/proj/file.c@@/main/1"

Another way for post-commit review is send changes developed on branch by
:option:`--tracking` option::

    $ post-review --tracking my_dev_branch

.. note::

   :command:`post-review` trying match reviewboard's repository based on
   VOB's UUID. In case of problems Your VOB's name will be used.
   Remember. You can always overwrite this behavior using
   :file:`.reviewboardrc `file or passing :option:`--repository-url`.


.. index:: post-commit review
.. _posting-committed-code:

Posting Committed Code
======================

By default, :command:`post-review` assumes that you're posting uncommitted
code. This is called a :term:`pre-commit review`. However, it's sometimes
useful to post code that has already been committed to a repository, such
as in an experimental branch. This is a :term:`post-commit review`.

In order to do this, you can use the :option:`--revision-range` parameter,
which will generate a diff based on a range of committed revisions.
This allows a single review request to show a diff representing the entire
history of a branch, if desired.

Usage is easy. Simply type::

    $ post-review --revision-range=STARTREV:STOPREV

Where ``STARTREV`` is the beginning revision in the range, and
``STOPREV`` is the ending revision, inclusive. If you only need to post
a single revision, you can type::

    $ post-review --revision-range=REVISION

In order to update an existing review request, you can use the
:option:`-r` parameter, as shown above.


.. _posting-existing-diffs:

Posting Existing Diffs
======================

:command:`post-review` will generate diffs automatically based on the
repository type, but if you need to post a pre-existing diff, you can
use the :option:`--diff-filename` parameter to specify the path to
the diff file.

For example::

    $ post-review --diff-filename=mycode.diff

You can also use the special value of ``-`` to pipe a diff into STDIN::

    $ cat mycode.diff | post-review --diff-filename=-

Using STDIN will require either a valid cookie, or the :option:`--username`
and :option:`--password` options.


.. _automating-post-review:

Automating post-review
======================

It's possible to automate :command:`post-review` on a user's behalf. This can
be useful from a repository's :term:`post-commit hook` to automatically
create or update a review request. This works through a combination of a
special Review Board user and the :option:`--submit-as` option.

To set this up, first register a new user. This user will be specific to
your script, and will have special permissions, so make sure the password
is protected. You'll then want to grant the
:ref:`can-submit-as-user-permission` and
:ref:`can-edit-review-request-permission` to the user. This will give this
user to the ability to modify a review request as another user.

You can then invoke :command:`post-review` by doing the following::

    $ post-review --username=SPECIAL_USER --password=PASSWORD --submit-as=ANOTHER_USER

Of course, you can pass any other values as you see fit.

This will log in as ``SPECIAL_USER`` and perform operations as
``ANOTHER_USER``.

You can set the default for :option:`--submit-as` by setting ``SUBMIT_AS``
in :file:`.reviewboardrc`.


Configuration
=============

There are many ways to configure :command:`post-review` in order to associate
a Review Board server with a repository. The ideal setup is to configure
a repository to point to a Review Board server, so that users can use
:command:`post-review` out of the box, but there are other methods available.


Repository Configuration
------------------------

Some repository types can have special metadata associated to point to a
server. All repository types support per-directory dot files.


Git Properties
~~~~~~~~~~~~~~

Repository information can be set in a ``reviewboard.url`` property on
the Git tree. Users may need to do this themselves on their own Git
tree, so in some cases, it may be ideal to use dotfiles instead.

To set the property on a Git tree, type::

    $ git config reviewboard.url http://reviewboard.example.com


Perforce Counters
~~~~~~~~~~~~~~~~~

Repository information can be set on Perforce servers by using
``reviewboard.url`` Perforce counters. How this works varies between versions
of Perforce.

Perforce version 2008.1 and up support strings in counters, so you can simply
do::

    $ p4 counter reviewboard.url http://reviewboard.example.com

Older versions of Perforce support only numeric counters, so you must encode
the server as part of the counter name. As ``/`` characters aren't supported
in counter names, they must be replaced by ``|`` characters. ``|`` is a
special character in shells, so you'll need need to escape these using ``\|``.
For example::

    $ p4 counter reviewboard.url.http:\|\|reviewboard.example.com 1


Subversion Properties
~~~~~~~~~~~~~~~~~~~~~

Repository information can be set in a ``reviewboard:url`` property on
a directory. This is usually done on whatever directory or directories
are common as base checkout paths. This usually means something like
:file:`/trunk` or :file:`/trunk/myproject`. If the directory is in the
user's checkout, it will be faster to find the property.

To set the property on a directory, type::

    $ svn propset reviewboard:url http://reviewboard.example.com .


.reviewboardrc
~~~~~~~~~~~~~~

The :file:`.reviewboardrc` file is a generic place for configuring a
repository. This must be in a directory in the user's checkout path to work.
It must parse as a valid Python file, or you'll see an error when using
:command:`post-review`.


REPOSITORY
^^^^^^^^^^

.. versionadded: 0.3.1

Normally, the repository path is automatically determined and passed to
Review Board, but on more complex setups you may need to tell
:command:`post-review` and Review Board specifically which repository you
want to use.

You can use the ``REPOSITORY`` setting to specify the path or the numeric
ID of the repository to use. For example::

    REPOSITORY = 'https://svn.example.com/'

If using Review Board 1.5.3 or higher, you can also choose to specify the
repository name. This is the same name as on Review Board's New Review Request
page. For example::

    REPOSITORY = 'RBTools'


REVIEWBOARD_URL
^^^^^^^^^^^^^^^

To specify the Review Board server to use, you can use the
``REVIEWBOARD_URL`` setting. This takes the URL to the Review Board server
as a value. For example::

    REVIEWBOARD_URL = "http://reviewboard.example.com"


Custom User Configuration
-------------------------

If the repository isn't configured for :command:`post-review` and a
custom script isn't provided, you can create a :file:`.reviewboardrc`
file in your HOME directory (usually :file:`/home/{username}` on Linux,
:file:`$USERPROFILE\\Local Settings\\Application Data` on Windows).

In the simplest case with only one Review Board server you'll ever
interact with, the file can simply contain::

    REVIEWBOARD_URL = "http://reviewboard.example.com"


A more complex setup for servers based on repository paths will look
more like::

    TREES = {
        'http://svn.example.com': {
            'REVIEWBOARD_URL': 'http://reviewboard.example.com',
        },
        'username@cvs.example.com:/cvsroot/cvs': {
            'REVIEWBOARD_URL': 'http://reviewboard.example.com',
        },
    }


Any number of repository paths can be specified. The repository path
must match a repository configured in the Review Board server.


Default Options
---------------

A number of options to post-review can be set by default in
:file:`.reviewboardrc`. These can go either in the repository's or the
user's :file:`.reviewboardrc` file.

The options include:

* ``BRANCH`` (:option:`--branch`)
* ``DEBUG`` (:option:`-d`)
* ``ENABLE_PROXY`` (:option:`--disable-proxy`)
* ``GUESS_DESCRIPTION`` (:option:`--guess-description`)
* ``GUESS_FIELDS`` (:option:`-g`)
* ``GUESS_SUMMARY`` (:option:`--guess-summary`)
* ``HTTP_PASSWORD`` (:option:`--http-password`)
* ``HTTP_USERNAME`` (:option:`--http-username`)
* ``OPEN_BROWSER`` (:option:`-o`)
* ``P4_CLIENT`` (:option:`--p4-client`)
* ``P4_PASSWD`` (:option:`--p4-passwd`)
* ``P4_PORT`` (:option:`--p4-port`)
* ``PARENT_BRANCH`` (:option:`--parent`)
* ``PASSWORD`` (:option:`--password`)
* ``PUBLISH`` (:option:`-p`)
* ``SUBMIT_AS`` (:option:`--submit-as`)
* ``TARGET_GROUPS`` (:option:`--target-groups`)
* ``TARGET_PEOPLE`` (:option:`--target-people`)
* ``TRACKING_BRANCH`` (:option:`--tracking-branch`)
* ``USERNAME`` (:option:`--username`)


Options
=======

Basic Options
-------------

.. cmdoption:: -d, --debug

   Displays detailed debug output in the terminal.

   The default can be set in ``DEBUG`` in :file:`.reviewboardrc`.

.. cmdoption:: -h, --help

   Shows the help for the program and exits.

.. cmdoption:: -o, --open

   Opens a web browser to the address of the review request.

   The default can be set in ``OPEN_BROWSER`` in :file:`.reviewboardrc`.

.. cmdoption:: --version

   Shows the version number and exits.


Server Options
--------------

.. cmdoption:: --disable-proxy

   Disables using any configured HTTP(S) proxy server when communicating
   with the Review Board server.

   The default can be set in ``ENABLE_PROXY`` in :file:`.reviewboardrc`.

.. cmdoption:: --server=<URL>

   Specifies the URL of Review Board server to use. By default,
   :command:`post-review` will try to scan for the correct repository.

   The default can be set in ``REVIEWBOARD_URL`` in :file:`.reviewboardrc`.

.. cmdoption:: --submit-as=<USERNAME>

   Specifies the username to use for any updates made to the review request.
   This is different than :option:`--username` in that this username is not
   used for logging in to the server. A login user with necessary
   permissions must be used in order for this parameter to work.

   This is useful when used in a repository's post-commit script to update
   a review request. See :ref:`automating-post-review` for usage information.

   The default can be set in ``SUBMIT_AS`` in :file:`.reviewboardrc`.

.. cmdoption:: --username=<USERNAME>

   Specifies the username used to log in to the Review Board server. If not
   specified, :command:`post-review` will prompt for it.

   The default can be set in ``USERNAME`` in :file:`.reviewboardrc`.

.. cmdoption:: --password=<PASSWORD>

   Specifies the password used to log in to the Review Board server. If not
   specified, :command:`post-review` will prompt for it.

   The default can be set in ``PASSWORD`` in :file:`.reviewboardrc`.

.. cmdoption:: --http-username=<USERNAME>

   Specifies the username to use when authenticating with Basic HTTP
   Authentication.

   The default can be set in ``HTTP_USERNAME`` in :file:`.reviewboardrc`.

.. cmdoption:: --http-password=<PASSWORD>

   Specifies the password to use when authenticating with Basic HTTP
   Authentication.

   The default can be set in ``HTTP_PASSWORD`` in :file:`.reviewboardrc`.


Review Request Options
----------------------

.. cmdoption:: -p, --publish

   Publishes the review request immediately after submitting. Normally
   the change is left as a draft.

   The default can be set in ``PUBLISH`` in :file:`.reviewboardrc`.

.. cmdoption:: --repository-url=<URL>

   Specifies the repository URL used when generating the diff.

   The default can be set in ``REPOSITORY`` in :file:`.reviewboardrc`.

.. cmdoption:: -r <ID>, --review-request-id=<ID>

   Updates an existing review request, instead of creating a new one. The
   ``ID`` is the review request number to use.

.. cmdoption:: --revision-range=<REVISION_RANGE>

   Specifies a revision or a range of revisions used to generate the diff.
   See :ref:`posting-committed-code` for usage information.


Field Defaults Options
----------------------

.. cmdoption:: --branch=<BRANCH>

   Sets the review request's branch field to the specified text.

   The default can be set in ``BRANCH`` in :file:`.reviewboardrc`.

.. cmdoption:: --bugs-closed=<BUGS_CLOSED>

   Specifies a list of bug numbers to use for the Bugs Closed section
   in the review request. This should be a comma-separated list.

.. cmdoption:: --description=<DESCRIPTION>

   Sets the description for the review request to the specified text.

.. cmdoption:: --description-file=<FILENAME>

   Sets the description for the review request to the contents of the
   specified file.

.. cmdoption:: --diff-filename=<FILENAME>

   Specifies an existing diff file to upload, instead of generating a new
   diff. The special value of ``-`` allows the diff to be piped into
   STDIN. See :ref:`posting-existing-diffs` for usage information.

.. cmdoption:: -g, --guess-fields

   Implies :option:`--guess-description` and :option:`--guess-summary`.

   This only works with Git and Mercurial.

   The default can be set in ``GUESS_FIELDS`` in :file:`.reviewboardrc`.

.. cmdoption:: --guess-description

   Sets the description of the review request based on all the commit
   messages between the parent branch and HEAD.

   This cannot be used with :option:`--description`.

   This only works with Git and Mercurial.

   The default can be set in ``GUESS_DESCRIPTION`` in :file:`.reviewboardrc`.

.. cmdoption:: --guess-summary

   Sets the summary of the review request based on the commit message of
   the most recent commit.

   This cannot be used with :option:`--summary`.

   This only works with Git and Mercurial.

   The default can be set in ``GUESS_SUMMARY`` in :file:`.reviewboardrc`.

.. cmdoption:: --summary=<SUMMARY>

   Sets the review request's summary field to the specified text.

.. cmdoption:: --target-groups=<TARGET_GROUPS>

   Provides a list of groups that should be on the reviewer list. This
   should be a comma-separated list.

   The default can be set in ``TARGET_GROUPS`` in :file:`.reviewboardrc`.

.. cmdoption:: --target-people=<TARGET_PEOPLE>

   Provides a list of usernames that should be on the reviewer list. This
   should be a comma-separated list.

   The default can be set in ``TARGET_PEOPLE`` in :file:`.reviewboardrc`.

.. cmdoption:: --testing-done=<TESTING_DONE>

   Sets the testing done text for the review request to the specified text.

.. cmdoption:: --testing-done-file=<FILENAME>

   Sets the testing done text for the review request to the contents of the
   specified file.


ClearCase Options
-----------------

.. cmdoption:: --label=<LABEL>

   Specifies the label used for ClearCase.


Git Options
-----------

.. cmdoption:: --tracking-branch=<BRANCH>

   Specifies a remote branch to use as the basis for the diff. This
   defaults to ``origin/master``, and should be used when a different
   remote branch is needed.

   The default can be set in ``TRACKING_BRANCH`` in :file:`.reviewboardrc`.


Git and Mercurial Options
-------------------------

.. cmdoption:: --parent=<PARENT_BRANCH>

   Specifies a parent branch that the diff should be based upon. This is
   useful when working on a branch based on another uncommitted branch.

   The default can be set in ``PARENT_BRANCH`` in :file:`.reviewboardrc`.

   See :ref:`DVCS` for usage information.


Perforce Options
----------------

.. cmdoption:: --change-only

   Updates the review request information (description, testing done, etc.)
   based on the change number provided, but doesn't update the diff.

.. cmdoption:: --diff-only

   Uploads the new diff, but doesn't modify the review request information
   (description, testing done, etc.) based on the change number provided.

.. cmdoption:: --p4-client=<P4_CLIENT>

   Specifies the Perforce client name that should be used when generating
   the diff.

   The default can be set in ``P4_CLIENT`` in :file:`.reviewboardrc`.

.. cmdoption:: --p4-port=<P4_PORT>

   Specifies the Perforce server IP address used when generating the diff.

   The default can be set in ``P4_PORT`` in :file:`.reviewboardrc`.

.. cmdoption:: --p4-passwd=<PASSWORD_OR_TICKET>

   Specifies the Perforce Ticket or clear-text password used to authenticate
   with the repository.

   The default can be set in ``P4_PASSWD`` in :file:`.reviewboardrc`.

.. comment: vim: ft=rst et ts=3
