# HG changeset patch # User Steve Losh # Date 1278999109 14400 # Node ID d0665eae3ef4b133f680e7348ecfd25567e0c70e # Parent cde269f2147e7931fa0a4ee3eb3318d8d90ddc29# Parent 466feb89a9d1cb65c18885a1a6f0704bdf8dc746 Merge documentation. diff -r cde269f2147e -r d0665eae3ef4 LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff -r cde269f2147e -r d0665eae3ef4 docs/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/Makefile Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,89 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/hg-review.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/hg-review.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff -r cde269f2147e -r d0665eae3ef4 docs/api.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/api.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,195 @@ +API +=== + +hg-review takes Mercurial's approach to API stability: + +* The command line interface is fairly stable and will not break often. +* File formats will not change often. +* The internal implementation may change frequently -- there are no guarantees + of stability. + +Providing a stable CLI means that (possibly non-GPL) programs can interact with +hg-review easily without fear of constant breaking. + +Stable file formats mean that older versions of hg-review will be able to work +with review data from newer versions (albeit with reduced functionality). + +*Not* providing a stable internal implementation allows hg-review's code to be +kept clean and elegant. It means that Python programs will needs to use +subprocesses to avoid breaking, but this is a tradeoff that the author feels is +worth making. + +Data Repository Layout +---------------------- + +The structure of hg-review's data repository looks like this:: + + your-project/ + | + +-- .hg/ + | | + | +-- review + | | | + | | +-- {{ changeset hash }} + | | | | + | | | +-- .exists + | | | | + | | | +-- comments + | | | | | + | | | | +-- {{ comment hash }} + | | | | | + | | | | `-- other comments... + | | | | + | | | +-- signoffs + | | | | + | | | +-- {{ signoff hash }} + | | | | + | | | `-- other signoffs ... + | | | + | | `-- other changesets ... + | | + | `-- other files ... + | + `-- other files ... + +All review data for a changeset is stored in:: + + .hg/review/{{ changeset hash }}/ + +A ``.exists`` file is included in that directory when code review for +that changeset is initialized. This allows us to check if a given changeset has +been initialized for code review very quickly. + +Comments for a changeset are stored in:: + + .hg/review/{{ changeset hash }}/comments/{{ comment hash }} + +Signoffs for a changeset are stored in:: + + .hg/review/{{ changeset hash }}/signoffs/{{ signoff hash }} + +File Formats +------------ + +hg-review's file format is (fairly) stable and is designed to be easily parsed +to enable export to other code review systems. + +Comment and signoff files are stored as JSON. The files are indented four +spaces per level to make them more human-readable. + +``.exists`` Files +''''''''''''''''' + +The ``.exists`` file is always empty. It simply exists to make looking up +whether a given changeset has been initialized faster. It may go away in the +future -- do not depend on it. + +Comment Files +''''''''''''' + +Here is a sample comment file:: + + { + "author": "Steve Losh ", + "file": [ + "reykjavi\u0301k.txt", + "cmV5YWphdmnMgWsudHh0" + ], + "hgdate": "Mon Jul 12 23:55:51 2010 -0400", + "lines": [ + 0 + ], + "message": "Sample.", + "node": "0e987f91e9b6628b26a30c5d00668a15fae8f22f", + "style": "markdown" + } + +Comment files have some or all of the following fields: + +``author`` + The Mercurial username of the person that added this comment. + +``file`` + A list of two strings. The first string is a (JSON-encoded) representation + of the UTF-8 filename. The second string is a base64 encoded version of the + actual bytes of the filename (which is what Mercurial gives and expects to + receive internally). If this is a review-level comment both strings will be + blank. + +``hgdate`` + The date and time the comment was added (or last edited). + +``lines`` + A list of integers representing the lines of the file that this comment + applies to. If this is a file-level or review-level comment the list will + be empty. + +``message`` + A string representing the raw comment message. + +``node`` + A string representing the hash of the changset this comment belongs to, for + easy lookup later. + +``style`` + A string representing the style of this comment -- this will be + ``markdown`` for Markdown comments and blank for plain-text comments. More + styles may be added in the future. + +Signoff Files +''''''''''''' + +Here is a sample signoff file:: + + { + "author": "Steve Losh ", + "hgdate": "Tue Jul 13 00:16:00 2010 -0400", + "message": "Sample.", + "node": "0e987f91e9b6628b26a30c5d00668a15fae8f22f", + "opinion": "yes", + "style": "markdown" + } + +Signoff files have some or all of the following fields: + +``author`` + The Mercurial username of the person that added this comment. + +``hgdate`` + The date and time the comment was added (or last edited). + +``message`` + A string representing the raw comment message. + +``node`` + A string representing the hash of the changset this comment belongs to, for + easy lookup later. + +``opinion`` + A string representing the signoff opinion. This will be ``yes``, ``no``, or + a blank string (for a neutral signoff). + +``style`` + A string representing the style of this comment -- this will be + ``markdown`` for Markdown comments and blank for plain-text comments. More + styles may be added in the future. + +Command Line Interface +---------------------- + +hg-review's command line interface is (fairly) stable. If you want to interact +with review data for a repository this is the safest method to use. + +See the :doc:`command line interface documentation ` for more details. + +Internal Python API +------------------- + +hg-review's internal Python implementation is *not* stable. It may change at +any time. Relying on it virtually guarantees your application will break at +some point. + +For a more stable API you should use the command line interface. + +The Python API will be documented later, but is not a high priority at the +moment because of its volatility. diff -r cde269f2147e -r d0665eae3ef4 docs/cli.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/cli.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,253 @@ +Command Line Interface +====================== + +hg-review provides a command line interface. Except for initializing the review +data, starting the web ui, and possibly some scripting, you'll probably want to +use the :doc:`web interface ` for most tasks. + +When you enable the hg-review extension Mercurial will gain a new command: +``review``. This command on its own will display review data for a changeset, +but it also has several subcommands detailed below. + +You can always get help on a given topic right from the command line with +``hg help review`` or ``hg help review-topic``. + +.. _c-review: + +``review`` +---------- + +View code review data for a changeset. Usage:: + + hg review [-r REV] [-U CONTEXT] [--quiet] [FILE] + +Diffs of all changed files will be shown with comments inline. + +The line numbers printed are the ones that should be used to add line-level +comments. + +Options: + +``--unified VALUE`` + The number of lines of context to show for diffs in this changeset + (default: ``5``). + +``--rev VALUE`` + The revision to show (default: ``.``). + +``--quiet`` + Do not show diffs -- only show review-level comments and signoffs (default: + ``false``). + +``--verbose`` + Show the short identifier of each comment and signoff, mainly for use with + the :ref:`edit ` subcommand (default: ``false``). + +``--debug`` + Show the full identifier of each comment and signoff, mainly for use with + the :ref:`edit ` subcommand (default: ``false``). + +.. _c-init: + +``--init`` +---------- + +Initialize code review for a repository. Usage:: + + hg review --init --remote-path PATH + +When run for the first time in a project, it will do two things: + +* Create a new repository to hold the review data at ``.hg/review/``. + +* Create and ``hg add`` a ``.hgreview`` file in the current repository. You + will need to commit this file yourself with: ``hg commmit .hgreview -m + 'initialize code review data'`` + +The ``--remote-path`` option is required and specifies the path where the +canonical code review data for this project will live. This is the path that +will be cloned when someone else runs ``hg review --init`` on the project. + +Options: + +``--remote-path VALUE`` + The URL to the public code review data repository. + + +.. _c-comment: + +``--comment`` +------------- + +Add a code review comment for a changeset. Usage:: + + hg review --comment [-m MESSAGE] [--mdown] [-r REV] [-l LINES] [FILE] + +If no files are given the comment will be attached to the changeset as a whole. + +If one or more files are given but no lines are given, the comment will be +attached to each file as a whole. + +If a file is given and lines are given the comment will be attached to those +specific lines. Lines should be specified as a comma-separated list of line +numbers (as numbered in the output of "hg review"), such as ``3`` or ``2,3``. + +Options: + +``--rev VALUE`` + The revision to add a comment to (default: ``.``). + +``--lines VALUE`` + Comment on the given lines (specified as a comma-separated list of line + numbers) of the file (default: ``None``). + +``--message VALUE`` + Use ``VALUE`` as the comment instead of opening an editor (default: + ``None`` (i.e. "open an editor")). + +``--mdown`` + Use Markdown to format the comment (default: ``False``). + + +.. _c-signoff: + +``--signoff`` +------------- + +Add a code review signoff for a changeset. Usage:: + + hg review --signoff [-m MESSAGE] [--mdown] [--yes | --no] [-r REV] + +The ``--yes`` and ``--no`` options can be used to indicate whether you think the +changeset is "good" or "bad". + +It's up to the collaborators of each individual project to decide exactly what +that means. If neither option is given the signoff will be marked as +"neutral". + +Options: + +``--rev VALUE`` + The revision to sign off on (default: ``.``). + +``--yes`` + Sign off as "yes" for the changeset (default: ``False`` (i.e. "neutral")). + +``--no`` + Sign off as "no" for the changeset (default: ``False`` (i.e. "neutral")). + +``--message VALUE`` + Use ``VALUE`` as the signoff message instead of opening an editor (default: + ``None`` (i.e. "open an editor")). + +``--mdown`` + Use Markdown to format the signoff message (default: ``False``). + + +.. _c-edit: + +``--edit`` +---------- + +Edit a comment or signoff. Usage:: + + hg review --edit IDENTIFIER [--yes | --no] [-m MESSAGE] [-l LINES] [--mdown] [FILE] + +Edit the comment or changeset with the given identifier. + +You can find the identifier of the item you would like to edit by running ``hg +review --verbose`` to display identifiers. + +Any other options given (such as ``--message``, ``--yes`` or filenames) will +replace the content of the item you edit. + +``--message VALUE`` + Replace the comment or signoff message with VALUE (default: ``None`` (i.e. + "open an editor")). + +``--mdown`` + Use Markdown to format the comment or signoff message (default: ``False`` + (i.e. "Use the same formatting the item already has)). + +``--lines`` + The line(s) of the file to comment on (default: ``None`` (i.e. "use the + same line the comment already has)). Returns an error if you're editing + a signoff or a review-level comment. + +``--yes`` + Change the signoff to state the the changeset is "good" (default: + ``False``). Returns an error if you are not editing a signoff. + +``--no`` + Change the signoff to state the the changeset is "bad" (default: + ``False``). Returns an error if you are not editing a signoff. + + +.. _c-check: + +``--check`` +----------- + +Check the review status of a changeset. Usage:: + + hg review --check [-r REV] [--no-nos] [--yeses NUM] [--seen] + +Check that the given changeset "passes" the given tests of review status. If no +tests are given an error is returned. + +Tests are checked in the following order: + +- ``--no-nos`` +- ``--yeses`` +- ``--seen`` + +If any tests fail the command returns a status of 1 with a message describing +the failure on stderr, otherwise it returns 0 and prints nothing. + +``--rev VALUE`` + The revision to check (default: ``.``). + +``--no-nos`` + Ensure this revision does *not* have any signoffs of "no" (default: + ``False`` (i.e. "Don't perform this check")). + +``--yeses VALUE`` + Ensure this revision has at least ``VALUE`` signoffs of "yes" (default: + ``None`` (i.e. "Don't perform this check"). + +``--seen`` + Ensure this revision has at least one comment or signoff (default: + ``False`` (i.e. "Don't perform this check")). + + +.. _c-web: + +``--web`` +--------- + +Start the web interface. Usage:: + + hg review --web [--read-only] [--allow-anon] [--address ADDRESS] [--port PORT] + +Visit http://localhost:8080/ (replace the port number if you specified +a different port) in a modern browser of your choice to use the web interface. + +Use ``Ctrl+C`` to stop the interface. + +Options: + +``--read-only`` + Make the web interface read-only; disallowing comments, signoffs, pushes + and pulls (default: ``False``). + +``--allow-anon`` + Allow anonymous comments on the web interface and set the username for + comments to an anonymous username (default: ``False`` (i.e. allow comments + and use your Mercurial username)). + +``--address VALUE`` + Run the web interface on the specified address (default: ``127.0.0.1``). + +``--port VALUE`` + Run the web interface on the specified port (default: ``8080``). + diff -r cde269f2147e -r d0665eae3ef4 docs/concepts.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/concepts.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,145 @@ +Concepts +======== + +You're not perfect. + +Your code is not perfect. + +If you're the only person that's reading your code, it's wrong. + +As developers we need to review each other's code. This helps us catch errors +before they find our users. It also makes us take greater care when writing +code because we know someone will be looking at it. + +Code Review Basics +------------------ + +The simplest form of code review is asking a friend to look at the code you +just wrote. Often a second set of eyes can find problems you might not have +seen, especially if that person has more experience than you. + +Unfortunately this isn't always practical. You might work remotely with people +thousands of miles away and not have a chance to simply turn around and say: +"Hey, could you look at this?" + +Code review tools (like hg-review) exist to make reviewing other people's code +easier. + +Their goal is to make it as easy as possible to tell another developer: "No, +you did *this* wrong. Fix it." + +Other Code Review Tools +----------------------- + +There are a lot of "code review tools" out there. + +The primary author of hg-review has a lot of experience with `Atlassian +Crucible `_, but some other +popular tools include: + +* `Rietveld `_ +* `Reviewboard `_ +* `Gerrit `_ +* `Code Collaborator `_ + +All of these tools try to accomplish the same goal: making it easy for +developers to tell each other how to write better code. + +hg-review has the same goal, but it goes about it a little differently. + +Distributed Code Review +----------------------- + +Let's back up for just a second and talk about version control. Some of the +most popular version control systems a few years ago were *centralized* systems +like `Subversion `_ and +`CVS `_. + +With these systems you had a central server that contained all the history of +your project. You would push changes to this central server and it would store +them. + +In the past half-decade or so there has been a move toward *decentralized* or +*distributed* version control systems. With these systems you commit to your +local machine and then *push* and *pull* your commits to other people. + +Code review tools, however, seem to have remained rooted in the "centralized +server" approach. Even the tools that support decentralized version control +systems like `git `_ and `Mercurial `_ +rely on a central server to store the code review data. + +hg-review does away with the "centralized data store" model and embraces +Mercurial's distributed nature. Code review data is held in a normal Mercurial +repository and can be pushed and pulled like any other type of data. + +This has several advantages, the biggest one being that you can review code +while offline without sacrificing any functionality. + +It also means that the full power of Mercurial (such as tracking history and +signing changesets with GPG) can be used on the review data. + +Review Data +----------- + +hg-review tracks two kinds of code review data: comments and signoffs. + +Comments are simple comments that people make about changesets. People can +comment on: + +* A changeset as a whole. +* A specific file within a changeset. +* One or more lines of a specific file within a changeset. + +Signoffs, on the other hand, *always* apply to a changeset as a whole. Each +person can have one signoff for any particular changeset (though they can edit +their signoff later). + +Signoffs can be used for whatever purpose your project might find useful, but +the author of hg-review recommends that signoffs of "yes" mean: + + I approve of this changeset and think it should make its way to production. + +And signoffs of "No" mean: + + I do not approve of this changeset and do not think it should make its way to + production without another changeset on top of it that fixes the problems + I have listed. + +Signoffs of "neutral" might mean: + + This changeset doesn't really impact me, so I don't care. + +Or perhaps: + + I've looked at this code but don't have the expertise to provide a useful + opinion. + + +Repository Structure +-------------------- + +While it's not necessary to know exactly how the guts of hg-review work, it +*is* helpful to understand the basic idea behind it. + +Let's say you have a project with a Mercurial repository in +``~/src/yourproject/`` and you'd like to start using hg-review with it. + +The first thing to understand is that Mercurial stores data about this local +repository in ``~/src/yourproject/.hg/``, and that data is local to your +machine. It is never committed or tracked by Mercurial, but is instead used by +the Mercurial program itself to work with your repository. + +hg-review creates a *separate* Mercurial repository to keep track of its data. +It stores this repository in ``~/src/yourproject/.hg/review/``. + +Because this is inside of Mercurial's internal ``.hg`` directory of your +project changes to the review data (like comments and signoffs) won't be +tracked in your project's repository. + +hg-review manages its own data in its own repository to avoid cluttering up +your project's log with useless "added a comment"-type commits. + +This structure means that you can ``cd`` into the review data repository itself +and interact with it just as you would a normal Mercurial repository. You can +``push`` and ``pull`` to and from other people, backout changesets and do +anything else you could with a normal Mercurial repository. diff -r cde269f2147e -r d0665eae3ef4 docs/conf.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/conf.py Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# +# hg-review documentation build configuration file, created by +# sphinx-quickstart on Mon Jun 14 20:39:45 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'hg-review' +copyright = u'2010, Steve Losh and contributors' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = 'pre-alpha' +# The full version, including alpha/beta/rc tags. +release = 'pre-alpha' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme_path = ['.'] +html_theme = 'hgreview' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'hg-reviewdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'hg-review.tex', u'hg-review Documentation', + u'Steve Losh', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff -r cde269f2147e -r d0665eae3ef4 docs/hacking.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/hacking.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,159 @@ +Hacking hg-review +================= + +Want to improve hg-review? Great! + +The easiest way is to make some changes, push them somewhere public and send +a pull request on Bitbucket (or `email Steve `_). + +Rough Guidelines +---------------- + +Here's a few tips that will make hg-review's maintainer happier. + +Basic Coding Style +'''''''''''''''''' + +Keep lines of code under 85 characters, unless it makes things *really* ugly. + +Indentation is four spaces. Tabs are evil. + +Commit Messages +''''''''''''''' + +Commit messages should start with a line like:: + + api: add feature X + +The first part is the component the change affects, like ``api``, ``cli``, +``web``, ``docs/api``, or ``guts``. + +``guts`` is a catchall for changesets that affect everything at once -- using +it means that the changeset could probably be split up into separate smallet +changesets. + +The rest of the commit message should describe the change. + +Tests +''''' + +Update the tests *in the same changeset as your change*. This makes bisection +by running the test suite easier. + +If your changeset changes the CLI output, make sure you've read the next +section and then add a test for it *in the same changeset*. + +If your changeset adds a new feature, add a test for it *in the same +changeset*. + +If your changeset fixes a bug, add a test that would reproduce the bug *in the +same changeset*. + +Backwards Compatibility +''''''''''''''''''''''' + +hg-review's internal implementation is not stable. Feel free to modify it +however you like. Patches that clean up the code and/or enhance performance +will be gladly accepted. + +hg-review's file format is stable, but new fields may be added at any time. +Removing a field or changing its format is not allowed without a very good +reason. Adding an entirely new file format may be acceptable if there is +a compelling reason. + +hg-review's command line interface is stable. Adding new commands or adding new +options to existing commands is fine if they prove useful. Removing commands or +radically changing the default output of existing commands is not acceptable +except in extreme cases. + +hg-review is currently compatible with Python 2.5+ and Mercurial 1.6+. Patches +that break this compatibility will be met with a large dose of skepticism. + +Layout +------ + +hg-review's basic structure looks like this:: + + hg-review/ + | + +-- bundled/ + | | + | `-- ... bundled third-party modules ... + | + +-- contrib/ + | | + | `-- ... useful items not critical to hg-review's core ... + | + +-- docs/ + | | + | `-- ... the documentation (and theme) ... + | + +-- review/ + | | + | +-- static/ + | | | + | | `-- ... static media for the web ui ... + | | + | +-- templates/ + | | | + | | `-- ... jinja2 templates for the web ui ... + | | + | +-- tests/ + | | | + | | ` ... unit test files and accompanying utilities ... + | | + | +-- api.py # the core hg-review backend + | | + | +-- cli.py # the hg-review Mercurial extension CLI + | | + | +-- messages.py # messages used by the CLI + | | + | +-- helps.py # help text for the CLI commands + | | + | +-- rutil.py # useful utilities + | | + | `-- web.py # the web interface + | + +-- README.markdown + | + +-- LICENSE + | + +-- fabfile.py + | + `-- kick.py + +Testing +------- + +hg-review contains a test suite for the command line interface (and therefore +the backend API as well). + +The tests can be run easily with nose. If you don't have node, you'll need to +install it first:: + + pip install nose + +Once you've got it you can run the suite by cd'ing to the hg-review directory +and running ``nosetests``. + +Before submitting a changeset please make sure it doesn't break any tests. + +If your changeset adds a new feature, add a test for it *in the same +changeset*. + +If your changeset fixes a bug, add a test that would reproduce the bug *in the +same changeset*. + +Documentation +------------- + +If you want to submit a patch, please update the documentation to reflect your +change (if necessary) *in the same changeset*. + +The documentation is formatted as restructured text and built with Sphinx +(version 0.6.7). + +The CSS for the documentation is written with LessCSS. If you want to update +the style you should update the ``docs/hgreview/static/review.less`` file and +render it to CSS. Include the changes to the ``.less`` file *and* the ``.css`` +file in your changeset. diff -r cde269f2147e -r d0665eae3ef4 docs/hgreview/static/aal.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/hgreview/static/aal.css Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,99 @@ +/* + aardvark.legs by Anatoli Papirovski - http://fecklessmind.com/ + Licensed under the MIT license. http://www.opensource.org/licenses/mit-license.php +*/ + +/* + Reset first. Modified version of Eric Meyer and Paul Chaplin reset + from http://meyerweb.com/eric/tools/css/reset/ +*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +header, nav, section, article, aside, footer +{border: 0; margin: 0; outline: 0; padding: 0; background: transparent; vertical-align: baseline;} + +blockquote, q {quotes: none;} +blockquote:before,blockquote:after,q:before,q:after {content: ''; content: none;} + +header, nav, section, article, aside, footer {display: block;} + +/* Basic styles */ +body {background: #fff; color: #111; font: 1em/1.5em "Helvetica Neue", Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif;} +html>body {font-size: 16px;} + +img {display: inline-block; vertical-align: bottom;} + +h1,h2,h3,h4,h5,h6,strong,b,dt,th {font-weight: 700;} +address,cite,em,i,caption,dfn,var {font-style: italic;} + +h1 {margin: 0 0 0.75em; font-size: 2em;} +h2 {margin: 0 0 1em; font-size: 1.5em;} +h3 {margin: 0 0 1.286em; font-size: 1.167em;} +h4 {margin: 0 0 1.5em; font-size: 1em;} +h5 {margin: 0 0 1.8em; font-size: .834em;} +h6 {margin: 0 0 2em; font-size: .75em;} + +p,ul,ol,dl,blockquote,pre {margin: 0 0 1.5em;} + +li ul,li ol {margin: 0;} +ul {list-style: outside disc;} +ol {list-style: outside decimal;} +li {margin: 0 0 0 2em;} +dd {padding-left: 1.5em;} +blockquote {padding: 0 1.5em;} + +a {text-decoration: underline;} +a:hover {text-decoration: none;} +abbr,acronym {border-bottom: 1px dotted; cursor: help;} +del {text-decoration: line-through;} +ins {text-decoration: overline;} +sub {font-size: .834em; line-height: 1em; vertical-align: sub;} +sup {font-size: .834em; line-height: 1em; vertical-align: super;} + +tt,code,kbd,samp,pre {font-size: 1em; font-family: Consolas, Monaco, "Courier New", Courier, monospace;} + +/* Table styles */ +table {border-collapse: collapse; border-spacing: 0; margin: 0 0 1.5em;} +caption {text-align: left;} +th, td {padding: .25em .5em;} +tbody td, tbody th {border: 1px solid #000;} +tfoot {font-style: italic;} + +/* Form styles */ +fieldset {clear: both;} +legend {padding: 0 0 1.286em; font-size: 1.167em; font-weight: 700;} +fieldset fieldset legend {padding: 0 0 1.5em; font-size: 1em;} +* html legend {margin-left: -7px;} +*+html legend {margin-left: -7px;} + +form .field, form .buttons {clear: both; margin: 0 0 1.5em;} +form .field label {display: block;} +form ul.fields li {list-style-type: none; margin: 0;} +form ul.inline li, form ul.inline label {display: inline;} +form ul.inline li {padding: 0 .75em 0 0;} + +input.radio, input.checkbox {vertical-align: top;} +label, button, input.submit, input.image {cursor: pointer;} +* html input.radio, * html input.checkbox {vertical-align: middle;} +*+html input.radio, *+html input.checkbox {vertical-align: middle;} + +textarea {overflow: auto;} +input.text, input.password, textarea, select {margin: 0; font: 1em/1.3 Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif; vertical-align: baseline;} +input.text, input.password, textarea {border: 1px solid #444; border-bottom-color: #666; border-right-color: #666; padding: 2px;} + +* html button {margin: 0 .34em 0 0;} +*+html button {margin: 0 .34em 0 0;} + +form.horizontal .field {padding-left: 150px;} +form.horizontal .field label {display: inline; float: left; width: 140px; margin-left: -150px;} + +/* Useful classes */ +img.left {display: inline; float: left; margin: 0 1.5em .75em 0;} +img.right {display: inline; float: right; margin: 0 0 .75em .75em;} diff -r cde269f2147e -r d0665eae3ef4 docs/hgreview/static/review.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/hgreview/static/review.css Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,228 @@ +@import url("aal.css"); +body, html { + background-color: #f8f7e8; + font-family: Georgia, serif; + color: #222; +} +body a, html a { + color: #b6410c; + text-decoration: none; +} +body a:hover, html a:hover { + text-decoration: underline; +} +body a.headerlink, html a.headerlink { + display: none; +} +body h1, +html h1, +body h2, +html h2, +body h3, +html h3, +body h4, +html h4, +body h5, +html h5, +body h6, +html h6 { + font-weight: normal; +} +body h1, html h1 { + letter-spacing: 1px; +} +body ul, html ul { + list-style-type: none; +} +body ul li, html ul li { + margin-left: 0; +} +body ul li li, html ul li li { + margin-left: 1em; +} +.related { + display: none; +} +.document { + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + border: 1px solid #edecc7; + margin: 25px auto 0px; + padding: 0px 00px; + width: 840px; +} +.document .documentwrapper { + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + background-color: #fbfbf3; + float: left; + width: 100%; +} +.document .documentwrapper .bodywrapper { + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + background-color: #fefefe; + margin-left: 230px; + border-left: 1px solid #edecc7; + padding: 20px 30px; + min-height: 700px; +} +.document .documentwrapper .bodywrapper div pre { + border: 1px solid #edecc7; + border-right: none; + background-color: #fbfbf3; + background-color: #f8f7e8; + font-size: 13px; + font-family: Monaco, Consolas, "Courier New", monospace; + line-height: 16px; + margin-bottom: 32px; + margin-top: -8px; + margin-left: 25px; + padding: 6px 8px; + width: 538px; + overflow-x: auto; +} +.document .documentwrapper .bodywrapper span.pre { + background-color: #fafaef; + border: 1px solid #edecc7; + padding: 0px 6px; + font-size: 13px; + font-family: Monaco, Consolas, "Courier New", monospace; + line-height: 24px; + white-space: pre; +} +.document .documentwrapper .bodywrapper ul { + list-style-type: disc; +} +.document .documentwrapper .bodywrapper ul li { + margin-left: 44px; +} +.document .documentwrapper .bodywrapper ul span.pre { + background-color: inherit; + border: none; + padding: 0; +} +.document .documentwrapper .bodywrapper ul li.toctree-l1 { + list-style-type: none; + margin-left: 0; +} +.document .documentwrapper .bodywrapper ul li.toctree-l2, .document .documentwrapper .bodywrapper ul li.toctree-l3 { + list-style-type: none; + margin-left: 30px; +} +.document .documentwrapper .bodywrapper a em { + font-style: normal; +} +.document .documentwrapper .bodywrapper tt.docutils.literal { + background-color: #fafaef; + border: 1px solid #edecc7; + padding: 0px 6px; + font-size: 13px; + font-family: Monaco, Consolas, "Courier New", monospace; + line-height: 24px; + white-space: pre; +} +.document .documentwrapper .bodywrapper tt.docutils.literal span.pre { + border: 0; + padding: 0; +} +.document .documentwrapper .bodywrapper .clear-code-effects { + border: none; + background: none; + padding: 0; + line-height: 1; +} +.document .documentwrapper .bodywrapper h1 tt.docutils.literal span.pre { + margin: 0 0 0.75em; + font-size: 2em; +} +.document .documentwrapper .bodywrapper h2 tt.docutils.literal span.pre { + margin: 0 0 1em; + font-size: 1.5em; +} +.document .documentwrapper .bodywrapper h3 tt.docutils.literal span.pre { + margin: 0 0 1.286em; + font-size: 1.167em; +} +.document .documentwrapper .bodywrapper h4 tt.docutils.literal span.pre { + margin: 0 0 1.5em; + font-size: 1em; +} +.document .documentwrapper .bodywrapper h5 tt.docutils.literal span.pre { + margin: 0 0 1.8em; + font-size: .834em; +} +.document .documentwrapper .bodywrapper h6 tt.docutils.literal span.pre { + margin: 0 0 2em; + font-size: .75em; +} +.document .documentwrapper .bodywrapper h1 tt.docutils.literal, +.document .documentwrapper .bodywrapper h2 tt.docutils.literal, +.document .documentwrapper .bodywrapper h3 tt.docutils.literal, +.document .documentwrapper .bodywrapper h4 tt.docutils.literal, +.document .documentwrapper .bodywrapper h5 tt.docutils.literal, +.document .documentwrapper .bodywrapper h6 tt.docutils.literal { + border: none; + background: none; + padding: 0; + line-height: 1; +} +.document .documentwrapper .bodywrapper h1 tt.docutils.literal span.pre, +.document .documentwrapper .bodywrapper h2 tt.docutils.literal span.pre, +.document .documentwrapper .bodywrapper h3 tt.docutils.literal span.pre, +.document .documentwrapper .bodywrapper h4 tt.docutils.literal span.pre, +.document .documentwrapper .bodywrapper h5 tt.docutils.literal span.pre, +.document .documentwrapper .bodywrapper h6 tt.docutils.literal span.pre { + font-weight: bold; + border: none; + background: none; + padding: 0; + line-height: 1; +} +.document .sphinxsidebar { + float: left; + margin-left: -100%; + width: 210px; + padding: 20px 20px; +} +.document .sphinxsidebar #searchbox h3 { + margin-bottom: 8px; +} +.document .sphinxsidebar #searchbox form input:nth-child(1) { + border: 1px solid #999; + font-size: 16px; +} +.document .sphinxsidebar #searchbox form input:nth-child(2) { + display: block; + margin-top: 6px; + width: 60px; +} +.document .sphinxsidebar #searchbox .searchtip { + display: none; +} +.document .sphinxsidebar .sphinxsidebarwrapper h4 { + margin-bottom: 0; +} +.document .sphinxsidebar .sphinxsidebarwrapper h3:nth-of-type(2) { + display: none; +} +.document .sphinxsidebar .sphinxsidebarwrapper ul.this-page-menu { + display: none; +} +.document .sphinxsidebar .sphinxsidebarwrapper ul li a span.pre { + font-size: 14px; + line-height: 24px; +} +.clearer { + clear: both; +} +.footer { + width: 840px; + margin: 8px auto 40px; + padding-right: 10px; + text-align: right; + font-style: italic; +} diff -r cde269f2147e -r d0665eae3ef4 docs/hgreview/static/review.less --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/hgreview/static/review.less Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,210 @@ +@import url("aal.css"); + +@c-cream: #edecc7; +@c-soft-cream: lighten(@c-cream, 10%); + +@font-normal: Georgia, serif; +@font-mono: Monaco, Consolas, "Courier New", monospace; +@content-width: 840px; + +.border-radius(@radius) { + -webkit-border-radius: @radius; + -moz-border-radius: @radius; + border-radius: @radius; +} + +body, html { + background-color: @c-soft-cream; + font-family: Georgia, serif; + color: #222; + + a { + color: #b6410c; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + &.headerlink { + display: none; + } + } + h1, h2, h3, h4, h5, h6 { + font-weight: normal; + } + h1 { + letter-spacing: 1px; + } + ul { + list-style-type: none; + + li { + margin-left: 0; + + li { + margin-left: 1em; + } + } + } +} +.related { + display: none; +} +.document { + .border-radius(8px); + border: 1px solid @c-cream; + margin: 25px auto 0px; + padding: 0px 00px; + width: @content-width; + + .documentwrapper { + .border-radius(8px); + background-color: lighten(@c-soft-cream, 3%); + float: left; + width: 100%; + + .bodywrapper { + .border-radius(8px); + background-color: #fefefe; + margin-left: 230px; + border-left: 1px solid @c-cream; + padding: 20px 30px; + min-height: 700px; + + div pre { + border: 1px solid @c-cream; + border-right: none; + background-color: lighten(@c-soft-cream, 3%); + background-color: @c-soft-cream; + font-size: 13px; + font-family: @font-mono; + line-height: 16px; + margin-bottom: 32px; + margin-top: -8px; + margin-left: 25px; + padding: 6px 8px; + width: @content-width - 302px; + overflow-x: auto; + } + span.pre { + background-color: lighten(@c-soft-cream, 2%); + border: 1px solid @c-cream; + padding: 0px 6px; + font-size: 13px; + font-family: @font-mono; + line-height: 24px; + white-space: pre; + } + ul { + list-style-type: disc; + + li { + margin-left: 44px; + } + span.pre { + background-color: inherit; + border: none; + padding: 0; + } + li.toctree-l1 { + list-style-type: none; + margin-left: 0; + } + li.toctree-l2, li.toctree-l3 { + list-style-type: none; + margin-left: 30px; + } + } + a em { + font-style: normal; + } + tt.docutils.literal { + background-color: lighten(@c-soft-cream, 2%); + border: 1px solid @c-cream; + padding: 0px 6px; + font-size: 13px; + font-family: @font-mono; + line-height: 24px; + white-space: pre; + + span.pre { + border: 0; + padding: 0; + } + } + .clear-code-effects { + border: none; + background: none; + padding: 0; + line-height: 1; + } + h1 tt.docutils.literal span.pre { margin: 0 0 0.75em; font-size: 2em; } + h2 tt.docutils.literal span.pre { margin: 0 0 1em; font-size: 1.5em; } + h3 tt.docutils.literal span.pre { margin: 0 0 1.286em; font-size: 1.167em; } + h4 tt.docutils.literal span.pre { margin: 0 0 1.5em; font-size: 1em; } + h5 tt.docutils.literal span.pre { margin: 0 0 1.8em; font-size: .834em; } + h6 tt.docutils.literal span.pre { margin: 0 0 2em; font-size: .75em; } + h1, h2, h3, h4, h5, h6 { + tt.docutils.literal { + .clear-code-effects; + + span.pre { + font-weight: bold; + .clear-code-effects; + } + } + } + } + } + .sphinxsidebar { + float: left; + margin-left: -100%; + width: 210px; + padding: 20px 20px; + + #searchbox { + h3 { + margin-bottom: 8px; + } + form { + input:nth-child(1) { + border: 1px solid #999; + font-size: 16px; + } + input:nth-child(2) { + display: block; + margin-top: 6px; + width: 60px; + } + } + .searchtip { + display: none; + } + } + .sphinxsidebarwrapper { + h4 { + margin-bottom: 0; + } + h3:nth-of-type(2) { + display: none; + } + ul.this-page-menu { + display: none; + } + ul li a span.pre { + font-size: 14px; + line-height: 24px; + } + } + } +} +.clearer { + clear: both; +} +.footer { + width: @content-width; + margin: 8px auto 40px; + padding-right: 10px; + text-align: right; + font-style: italic; +} diff -r cde269f2147e -r d0665eae3ef4 docs/hgreview/theme.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/hgreview/theme.conf Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,5 @@ +[theme] +inherit = basic +stylesheet = review.css +pygments_style = none + diff -r cde269f2147e -r d0665eae3ef4 docs/index.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/index.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,66 @@ +.. hg-review documentation master file, created by + sphinx-quickstart on Mon Jun 14 20:39:45 2010. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +hg-review documentation +======================= + +hg-review is a `Mercurial `_ extension for performing +distributed `code review `_. + +Quickstart +---------- + +If you're impatient and want to play with hg-review right away, here's what you +need to do. + +First, clone the extension somewhere:: + + hg clone http://bitbucket.org/sjl/hg-review/ + +Then add it to your ``~/.hgrc`` file:: + + [extensions] + review = [path to]/hg-review/review/ + +Now you need a repository that has code review enabled. Luckily, you've +already got one -- hg-review uses itself for code review. + +``cd`` into the directory you cloned hg-review to and initialize the review +data, then start the web interface:: + + cd hg-review + hg review --init + hg review --web + +Open http://localhost:8080/ in your browser of choice and poke around. Check +out the :doc:`Overview ` when you're ready to learn more. + +User's Guide +------------ + +If you want to use hg-review for anything more than some simple poking around, +this is the place to start. + +.. toctree:: + :maxdepth: 2 + + overview + concepts + webui + cli + +Developer's Guide +----------------- + +If you want to integrate hg-review with your own application or Mercurial +extension, or hack on hg-review itself, this is what you need to know. + +.. toctree:: + :maxdepth: 2 + + api + hacking + licensing + diff -r cde269f2147e -r d0665eae3ef4 docs/kick --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/kick Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +kicker -qs -l 0.1 -e reload_safari \ +_build/**/* diff -r cde269f2147e -r d0665eae3ef4 docs/kick-content --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/kick-content Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +kicker -qs -l 0.1 -e 'make html; reload_safari' \ +*.rst diff -r cde269f2147e -r d0665eae3ef4 docs/licensing.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/licensing.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,28 @@ +Licensing +========= + +hg-review is distributed under the same license as Mercurial itself: `GPL +version 2 or any later version +`_. + +If you want to create a program that works with hg-review you should look at +`Mercurial's License FAQ page `_ to +learn about how this might affect you. + +The basic idea is: + +* If you review code with hg-review, you are not affected by the license. +* If you bundle hg-review with another application and don't change anything, + you are not affected by the license. +* If you create an application that interacts with hg-review solely through its + command line interface or web interface, you are not affected by the license. +* If you create an application that interactes with hg-review by calling its + internal Python API, you *are* affected by the license and will need to + license your application's code as GPL version 2 or later. + +Note that the last item (using hg-review's internal Python API) is probably the +one you *won't* want to do anyway, since the Python API is *not* stable. + +If you have any questions please `email Steve `_, +but remember that he's not a lawyer and might not have a fast answer for tricky +questions. diff -r cde269f2147e -r d0665eae3ef4 docs/overview.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/overview.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,93 @@ +Overview +======== + +Let's get started using hg-review. No matter how you want to use it, you need +to install it first. + +Installation +------------ + +hg-review requires `Python `_ 2.5 or later and `Mercurial +`_ 1.6 or later. + +You probably have both of these requirements already, but if you encounter +problems you might want to check these first with ``python --version`` and +``hg --version``. + +hg-review also depends on a couple of other things like `Flask +`_ and `Jinja2 `_, but it +bundles these requirements so you don't need to worry about them. + +To install hg-review, first clone the extension somewhere:: + + hg clone http://bitbucket.org/sjl/hg-review/ + +Then add it to your ``~/.hgrc`` file:: + + [extensions] + review = [path to]/hg-review/review/ + +Usage +----- + +The easiest way to work with hg-review is with the :doc:`web interface +`. There's also a :doc:`command-line interface `, but it's +easiest to work with the web interface. + +Projects with Existing Code Reviews +''''''''''''''''''''''''''''''''''' + +If you want to work with a repository that already has code review set up all +you need to do is cd into that repository, pull down the review data, and fire +up the web ui:: + + cd ~/src/someproject + hg review --init + hg review --web + +Once that's done you can visit http://localhost:8080/ in your browser to start +reviewing. + +You should read over the :doc:`concepts ` documentation to make sure +you know how hg-review works and the :doc:`web interface ` +documentation for a quick tour of how to use the web UI. + +Projects without Existing Code Reviews +'''''''''''''''''''''''''''''''''''''' + +If you want to *start* using hg-review with a repository, you need to do a few +things to get it ready. + +First, create a repository to hold the code review data. This repository should +be in a location that's accessible by anyone that needs to see the review data. + +For example, if you're working on an open-source project that's hosted at +http://bitbucket.org/you/project/ you should create a new repository for +the review data at http://bitbucket.org/you/project-review/ + +Next you'll need to initialize the review data in your project. ``cd`` into you +project's directory and run:: + + hg review --init --remote-path URL + +The ``URL`` should be the *public* URL of the review repo you just created. + +This will create a local review data repo for you, as well as an ``.hgreview`` +file in your project. You need to commit this ``.hgreview`` file to your +project with the command that hg-review suggested. + +Don't worry, this is the only time hg-review will make you commit something to +your project's repository and clutter up its changelog. + +Now you can get to work reviewing changesets with the web interface by +running ``hg review --web`` in your project. + +You should read over the :doc:`concepts ` documentation to make sure +you know how hg-review works, and the :doc:`web interface ` +documentation for a quick tour of how to use the web UI. + +Reporting Bugs +-------------- + +If you encounter any errors while using hg-review please `post a bug +`_. diff -r cde269f2147e -r d0665eae3ef4 docs/publish.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/publish.sh Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +make html +rsync --delete -az _build/html/ ~/src/sjl.bitbucket.org/hg-review +hg -R ~/src/sjl.bitbucket.org commit -Am 'hg-review: Update documentation.' +hg -R ~/src/sjl.bitbucket.org push diff -r cde269f2147e -r d0665eae3ef4 docs/webui.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/webui.rst Tue Jul 13 01:31:49 2010 -0400 @@ -0,0 +1,164 @@ +Web Interface +============= + +The web interface of hg-review is probably what you're going to use the most. + +Running Locally +--------------- + +To start the web interface for a local repository that you want to review you +can run ``hg review --web``. Visit http://localhost:8080/ to use it. + +When you add comments or signoffs hg-review will use your normal Mercurial +username as the author. + +This command can take a few extra options: + +``--address ADDRESS`` + The address to bind to. Use ``0.0.0.0`` if you want other people to be able + to access it. + + **Be careful!** Because the web interface uses your Mercurial username by + default, binding to ``0.0.0.0`` will let anyone add comments and signoffs + in your name! You'll probably want to use the ``--read-only`` option to + prevent this. + + Default: ``127.0.0.1`` + +``--port PORT`` + The port to listen on. + + Default: ``8080`` + +``--read-only`` + Run the server in read-only mode. This will not allow data to be pushed or + pulled, comments to be made or signoffs to be added. + + This can be useful when combined with ``--address`` to let other people + view the UI without letting them add comments in your name. + + Default: ``false`` + +``--allow-anon`` + Allow comments (not not signoffs) to be added even if ``--read-only`` is + used, and set the username to ``Anonymous `` instead + of your Mercurial username. + + This option is most useful when you're deploying a permanent web interface + to a server and want to allow anonymous viewers to add comments. See the + :ref:`deployment` section for more information. + + Default: ``false`` + + +.. _deployment: + +Deployment to a Server +---------------------- + +Although hg-review is built for *distributed* code review it's sometimes nice +to provide a public interface. This will let people can comment easily without +using the extension (or even cloning your project). + +Initial Deployment +'''''''''''''''''' + +You can use any WSGI server you like to provide a public instance of hg-review. +Before you start you'll need to have Mercurial installed on your web server. + +Once you've got Mercurial running on the server you'll need to clone copies of +hg-review, your project, and your project's review data to the web server. +First create a directory where everything will live:: + + mkdir /var/www/myproject-review-interface/ + cd /var/www/myproject-review-interface/ + +Then grab a copy of hg-review:: + + hg clone http://bitbucket.org/sjl/hg-review/ + +Grab a copy of your project and configure it to use the hg-review extension as +well as the built-in `fetch +`_ extension (to +automatically merge updates):: + + hg clone -U http://bitbucket.org/you/yourproject/ + cd yourproject + + echo '[extensions]' >> .hg/hgrc + echo 'review = /var/www/myproject-review-interface/hg-review/review' >> .hg/hgrc + echo 'fetch = ' >> .hg/hgrc + +Use hg-review to pull down the review data:: + + hg review --init + +Now that you've got all the necessary data you can set up the WSGI script. +Start by copying the included sample script:: + + cd /var/www/myproject-review-interface/ + cp hg-review/contrib/deploy/wsgi.py wsgi.py + +Edit the script to configure your project to your liking. For reference, the +relevant part of the script should look something like this:: + + # An example WSGI script for serving hg-review's web UI. + # Edit as necessary. + + # If hg-review is not on your webserver's PYTHONPATH, uncomment the lines + # below and point it at the hg-review directory. + import sys + sys.path.insert(0, "/var/www/myproject-review-interface/hg-review") + + REPO = '/var/www/myproject-review-interface/myproject' + READ_ONLY = True + ALLOW_ANON_COMMENTS = False + ANON_USER = 'Anonymous ' + SITE_ROOT = 'http://yoursite.com/optional/path' + TITLE = 'Your Project' + PROJECT_URL = 'http://bitbucket.org/your/project/' # or None + +All that's left is to point your WSGI server at this script and fire it up. How +you do that depends on your WSGI server. A sample configuration file for +`Gunicorn `_ is provided in +``contrib/deploy/gunicorn.conf.py``. + +Updating the Data +''''''''''''''''' + +You'll want to keep the review data for this interface current so users can see +all the latest comments and signoffs. + +To do this you simply need to pull in the main repository (to receive new +changesets in your project) and fetch in the review data repository (to receive +new comments and signoffs):: + + hg -R /var/www/myproject-review-interface/ pull + hg -R /var/www/myproject-review-interface/.hg/review fetch + +New comments and signoffs will be visible immediately -- you don't need to +restart your WSGI server. + +You'll probably want to set this up as a cron job or use a hook of some kind +to automate the updates. + +If you allow anonymous comments and want people that are using the extension +locally (instead of this public instance) to see these comments, you'll need to +*fetch and push* the review data repo as well:: + + hg -R /var/www/myproject-review-interface/.hg/review/ fetch + hg -R /var/www/myproject-review-interface/.hg/review/ push + +hg-review is designed to never encounter merge conflicts with its data, but +there's always the chance that someone has done something manually that could +cause a problem. + +If your interface doesn't seem to be receiving new comments/signoffs you'll +want to take a look at the review data repository to see what's wrong:: + + cd /var/www/myproject-review-interface/.hg/review + hg heads + +There should only ever be one head in this repository. If there are more you'll +need to merge them (and push back to your public review data repo so others +won't encounter the same problem). diff -r cde269f2147e -r d0665eae3ef4 review/static/style.less