{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "$$\n", "\\def\\CC{\\bf C}\n", "\\def\\QQ{\\bf Q}\n", "\\def\\RR{\\bf R}\n", "\\def\\ZZ{\\bf Z}\n", "\\def\\NN{\\bf N}\n", "$$\n", "# Tutorial: How to contribute to Sage (outdated)\n", "\n", "Prerequisites:\n", "\n", "- [tutorial-editing-sage-sources](tutorial-editing-sage-sources.ipynb).\n", "\n", "This tutorial is outdated since 2013 (Sage 6.0), when Sage development's workflow was deeply refactored, including a switch to the version control system git instead of Mercurial.\n", "\n", "See instead the [Developers Guide](http://www.sagemath.org/doc/developer/).\n", "\n", "## GNU General Public Licence\n", "\n", "Sage is distributed under the terms of the GNU General Public License version 2 ([GPLv2](http://www.gnu.org/licenses/)) which provides four kinds of freedom:\n", "\n", "- Freedom to run the program\n", "- Freedom to study the code\n", "- Freedom to change the code\n", "- Freedom to redistribute your changes to anyone, improve the software\n", "\n", "All users of Sage make use of the first freedom. In \\* [tutorial-editing-sage-sources](tutorial-editing-sage-sources.ipynb) we used the second and third. Here we will see how to use the last one.\n", "\n", "## Sixteen Easy Steps\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
    \n", "
  1. Find a bug
  2. \n", "
    \n", "
  1. Verify the content the patch
  2. \n", "
    \n", "
  1. Sage trac server
  2. \n", "
    \n", "
  1. Upload the patch on Sage trac
  2. \n", "
    \n", "
  1. Create a ticket
  2. \n", "
    \n", "
  1. More on Mercurial queues
  2. \n", "
    \n", "
  1. Edit the sage sources
  2. \n", "
    \n", "
  1. Download a patch
  2. \n", "
    \n", "
  1. Enable Mercurial queues
  2. \n", "
    \n", "
  1. Edit the series file
  2. \n", "
    \n", "
  1. Create a patch
  2. \n", "
    \n", "
  1. Reviewing a patch
  2. \n", "
    \n", "
  1. Update the current patch
  2. \n", "
    \n", "
  1. Positive review or Needs work
  2. \n", "
    \n", "
  1. Export a patch
  2. \n", "
    \n", "
  1. Advanced tricks
  2. \n", "
\n", "\n", "Are you ready?\n", "\n", "## 1. Find a bug\n", "\n", "That's the easiest part :-) If you don't have one, you may browse the [Open Beginner Tickets](http://trac.sagemath.org/sage_trac/query?status=new&keywords=~beginner).\n", "\n", "Here, we will fix a typo in the documentation of sage.modular.modform.element.ModularForm\\_abstract.qexp.\n", "\n", "## 2. Sage trac server\n", "\n", "In Sage, modifications are tracked on a web site called [Sage trac](http://trac.sagemath.org). Every bug gets assigned a number. For instance, the number [\\#10484](http://trac.sagemath.org/sage_trac/ticket/10484) refers to the bug called Chinese remainder code raises an error when called\n", "with Python ints. On the ticket, one can see that:\n", "\n", "- The bug was reported and solved by **David Loeffler** (UK) in December 2010.\n", "- The ticket was positively reviewed by **Robert Bradshaw** (USA) and **Mike Hansen**.\n", "- The solution was merged in `sage-4.6.2` by **Jeroen Demeyer** (Belgium) on January 11th 2011.\n", "\n", "One can also look at the solution, download it, test it, etc.\n", "\n", "## 3. Create a ticket\n", "\n", "In order to create a ticket:\n", "\n", "- Get an account, following the instructions on .\n", "- Make sure the ticket does not already exists.\n", "- Login to your account\n", "- Create ticket\n", "- In the description field, explain how someone else should understand and/or reproduce the bug.\n", "\n", "Here, we create the ticket \\#11299 for fixing the documentation of sage.modular.modform.element.ModularForm\\_abstract.qexp.\n", "\n", "## 4. Edit the sage sources\n", "\n", "See [tutorial-editing-sage-sources](tutorial-editing-sage-sources.ipynb).\n", "\n", "## 5. Enable Mercurial queues\n", "\n", "**Mercurial queues** is an extension to Mercurial that allows one to easily work with collections of patches. To allow Mercurial queues, edit (or create) the file `~/.hgrc` and make sure it contains *your* user name, and the line **hgext.mq =** in the `extensions` section:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[ui]\n", "username = Sebastien Labbe \n", "\n", "[extensions]\n", "hgext.mq =\n", "color =\n", "\n", "[alias]\n", "qstatus = status --rev -2:." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you plan on joining the Sage-Combinat community, you may as well create at once [a full featured .hgrc](http://wiki.sagemath.org/combinat/MercurialStepByStep#Mercurialconfiguration)\n", "\n", "## 6. Create a patch\n", "\n", "Create a patch:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hg qnew trac_11299-fix_modform_element_qexp_documentation-nt.patch" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Often one starts instead by creating an empty patch, and then puts the modifications in there.\n", "\n", "No changes are shown anymore by **hg status** or **hg diff**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> **hg status**\n", "> **hg diff**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Modifications are now in the patch. See **hg qstatus** or **hg qdiff**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> **hg qstatus**\n", "> **hg qdiff**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Update the current patch\n", "\n", "Anytime one is happy with the current modifications, one may *update the current patch* with **hg qrefresh** to reflect the changes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> **hg qrefresh**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After that, **hg status** and **hg diff** will report changes with respect to the last **hg qrefresh**.\n", "\n", "## 8. Export a patch\n", "\n", "When the bug is fixed, once we made sure every tests pass and that the documentation builds fine, then we can export the current patch. First we Add a commit message to the patch:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> **hg qrefresh -m \"#11299: fix the documentation of ...\"**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Export the patch with **hg export**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> **hg export trac_11299-fix_modform_element_qexp_documentation-nt.patch > /tmp/trac_11299-fix_modform_element_qexp_documentation-nt.patch**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The command **hg export** also adds informations in the patch (author name, date, ...).\n", "\n", "Personally, I added the following alias to my `~/.bashrc` :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "alias qtoptotmp='hg export `hg qtop` > ~/Documents/tmp/`hg qtop`'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 9. Verify the content the patch\n", "\n", "Here is an example of a patch exported by `Mercurial` for the ticket \\#11299. It contains information about the author, the date, the commit message we just wrote and finally the complete diff :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> **cat /tmp/trac_11299-fix_modform_element_qexp_documentation-nt.patch**\n", "# HG changeset patch\n", "# User Nicolas M. Thiery \n", "# Date 1304605845 10800\n", "# Node ID deaba508575826bc715e019f77e7ce0d2bbe285c\n", "# Parent 361a4ad7d52c69b64ae2e658ffd0820af0d87e93\n", "#11299: Fix the documentation of modform_element.qexp\n", "\n", "diff --git a/sage/modular/modform/element.py b/sage/modular/modform/element.py\n", "--- a/sage/modular/modform/element.py\n", "+++ b/sage/modular/modform/element.py\n", "@@ -199,17 +199,17 @@ class ModularForm_abstract(ModuleElement\n", "\n", " def qexp(self, prec=None):\n", " \"\"\"\n", "- Same as self.q_expansion(prec).\n", "+ Same as ``self.q_expansion(prec)``.\n", "\n", "- .. seealso: :meth:`q_expansion`\n", "+ .. seealso:: :meth:`q_expansion`\n", "\n", " EXAMPLES::\n", "- \n", "+\n", " sage: CuspForms(1,12).0.qexp()\n", "- q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6) \n", "+ q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)\n", " \"\"\"\n", " return self.q_expansion(prec)\n", "- \n", "+\n", "\n", " def __eq__(self, other):\n", " \"\"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 10. Upload the patch on Sage trac\n", "\n", "From the [ticket page](http://trac.sagemath.org/sage_trac/ticket/?????), **upload the patch on Sage trac**. You can mention things like *\"tested on sage-4.6.2\"* in the text box when uploading the ticket.\n", "\n", "Make sure the patch was correctly uploaded by looking at it directly on the web page.\n", "\n", "**Set the ticket to needs review**\n", "\n", "You may ask somebody to review your ticket, typically by adding his trac login in the CC field.\n", "\n", "## 11. More on Mercurial queues\n", "\n", "Other useful Mercurial commands when managing several patches:\n", "\n", "**hg qnew** \n", "Create a new patch\n", "\n", "**hg qnew** \n", "...\n", "\n", "**hg qpop** \n", "Move a patch from the applied stack to the unapplied one\n", "\n", "**hg qpush** \n", "Move a patch from the unapplied stack to the applied one\n", "\n", "**hg qtop** \n", "Show the current patch\n", "\n", "**hg qseries** \n", "Print all of the patches in order\n", "\n", "**hg qapplied** \n", "Print the applied stack\n", "\n", "**hg qunapplied** \n", "Print the unapplied stack\n", "\n", "**hg qdelete trac\\_65321-nice-feature-AA.patch** \n", "Delete an (unapplied) patch from the queue\n", "\n", "**hg log** \n", "Print the revision history of the specified files or the entire project:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> cd /opt/sage/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> hg log\n", "\n", "> changeset: 15205:f24ce048fa66 tag: tip user: Jeroen Demeyer date: Tue Jan 11 08:10:26 2011 +0100 summary: 4.6.1\n", ">\n", "> ...\n", ">\n", "> changeset: 0:039f6310c6fe user: tornaria date: Sat Feb 11 01:13:08 2006 +0000 summary: \\[project @ original sage-0.10.12\\]\n", "\n", "**hg update ...** \n", "Update the repository's working directory to the specified changeset.\n", "\n", "## 12. Download a patch\n", "\n", "A feature available on a Sage Trac ticket is of interest to you? You want to review a ticket?\n", "\n", "Download a patch!\n", "\n", "Insert a patch into the series after the last applied patch with **hg qimport**, and then apply it with **hg qpush**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> hg qimport ~/Downloads/trac_65321-nice-feature-AA.patch\n", "> hg qpush\n", "Applying trac_65321-nice-feature-AA.patch\n", "Currently at : trac_10056-new_oeis_address-tm.patch" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do NOT use the command **hg import** as it will import the changes in the current patch.\n", "\n", "## 13. Edit the series file\n", "\n", "You can change the order in which the patches are applied. To do so, simply edit the **series** file:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "/opt/sage/devel/sage/.hg/patches/series" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make sure the patch you are reviewing is the first patch to be applied:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> cd /opt/sage/devel/sage/.hg/patches/\n", "> cat series\n", "trac_65321-nice-feature-AA.patch\n", "A.patch\n", "B.patch\n", "C.patch" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Patches might not commute, for example if they edit the exact same line. If conflicts occur after editing the series file and doing **hg qpush**, simply edit the series file and try again.\n", "\n", "## 14. Reviewing a patch\n", "\n", "Visit the [Reviewing a patch](http://www.sagemath.org/doc/developer/walk_through.html#reviewing-a-patch) Section of the Sage Developer's Guide. Also, make sure you read William Stein's [blog post](http://sagemath.blogspot.com/2010/10/how-to-referee-sage-trac-tickets.html) about reviewing a Sage trac ticket.\n", "\n", "Make sure the patch applies on Sage without conflicts:\n", "\n", "> > hg qpush\n", "\n", "Experiment the functionality proposed in the patch.\n", "\n", "- Make sure the bug described in the ticket is fixed.\n", "- Make sure the patch does not introduce any new bug.\n", "\n", "Run tests on the affected files:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> sage -t " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test the entire Sage library.\n", "\n", "> > sage --testall --long\n", "\n", "Ensure that the documentation builds fine:\n", "\n", "> > sage -docbuild reference html\n", "\n", "Check for full 100% doctest coverage:\n", "\n", "> > sage -coverage <file>\n", "\n", "Once you\u2019ve tested the patch, report any failures on the Trac page for the ticket. Make suggestions about simplifying the code or fixing typos you noticed.\n", "\n", "The experimental [Sage patch buildbot](http://wiki.sagemath.org/buildbot) automatizes some of the steps.\n", "\n", "## 15. Positive review or Needs work\n", "\n", "Three cases may happen:\n", "\n", "**Needs work** \n", "If there is anything to do, describe it precisely in a comment, and change the status of the ticket to **needs work**.\n", "\n", "**Positive review** \n", "Otherwise, mark it as **positive review**, and mention in a comment all the things you checked.\n", "\n", "**Delegate** \n", "If you feel unqualified for some aspects of the review, add a comment on the ticket explaining what you have checked, what the results were, and that you think someone more experienced should take a look at.\n", "\n", "Feedback on tickets is always useful!\n", "\n", "In Sage, a **negative review** does not exist! There is always room for work and improvement!\n", "\n", "## 16. Advanced tricks\n", "\n", "### 19.1 Clone your version of Sage\n", "\n", "**Clone Sage and create your branch** (Do it right now because it might take some time) \n", "`sage -clone slabbe`\n", "\n", "This creates a new directory called `sage-slabbe` in the `devel` repository:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "slabbe@pol /opt/sage/devel $ ls -l\n", "drwxr-xr-x 2 slabbe staff 68 14 jan 03:59 old/\n", "lrwxr-xr-x 1 slabbe staff 9 18 jan 15:01 sage -> sage-main/\n", "drwxr-xr-x 23 slabbe staff 782 18 jan 01:42 sage-main/\n", "drwxr-xr-x 24 slabbe staff 816 17 jan 01:50 sage-slabbe/\n", "lrwxr-xr-x 1 slabbe staff 11 14 jan 03:42 sagenb -> sagenb-main/\n", "drwxr-xr-x 21 slabbe staff 714 14 jan 03:41 sagenb-main/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**cd to your branch**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> cd /opt/sage/devel/sage-slabbe" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> - - `sage -br` --\n", "\n", "### 19.2. Do some cleaning\n", "\n", "Delete an (unapplied) patch from the queue:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> hg qdelete trac_65321-nice-feature-AA.patch" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Erase your branch. Of course, do this only if you don't care about your local changes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "> sage -b main\n", "> rm -rf /opt/sage/devel/sage-slabbe" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## References\n", "\n", "[Sage](http://www.sagemath.org)\n", "\n", "[Sage trac]()\n", "\n", "[Sage Developer's Guide](http://www.sagemath.org/doc/developer/index.html)\n", "\n", "[Reviewing a Sage trac ticket](http://sagemath.blogspot.com/2010/10/how-to-referee-sage-trac-tickets.html), William Stein's blog post, October 31, 2010.\n", "\n", "This talk was generated\n", "\n", "- by [Docutils](http://docutils.sourceforge.net/)\n", "- from [ReStructuredText](http://docutils.sourceforge.net/rst.html) source\n", "- to a [Simple Standards-based Slide Show System (S5)](http://docutils.sourceforge.net/docs/user/slide-shows.html) format." ] } ], "metadata": { "kernelspec": { "display_name": "sagemath", "name": "sagemath" } }, "nbformat": 4, "nbformat_minor": 2 }