1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
******************
Contributing guide
******************
Thanks for your interest in contributing to cpplint.
Any kinds of contributions are welcome: Bug reports, Documentation, Patches. However, here are some contributions you probably shouldn't make:
* Drastic reorganization
* Making the code conform to Google's Python style guidelines
* Features that could be regarded as a security vulnerability
If you need some ideas, you may check out some of the tasks in our `issue tracker <https://github.com/cpplint/cpplint/issues>`_.
Development
===========
For many tasks, it is okay to just develop using a single installed python version. But if you need to test/debug the project in multiple python versions, you need to install those versions:
1. (Optional) Install multiple python versions
1. (Optional) Install `pyenv <https://github.com/pyenv/pyenv-installer>`_ to manage python versions
2. (Optional) Using pyenv, install the python versions used in testing::
pyenv install 3.<version>
# ...
pyenv local 3.<version> ...
It may be okay to run and test python against locally installed libraries, but if you need to have a consistent build, it is recommended to manage your environment using virtualenv: `virtualenv <https://virtualenv.pypa.io/en/latest/>`_, `virtualenvwrapper <https://pypi.org/project/virtualenvwrapper/>`_::
mkvirtualenv cpplint [-p /usr/bin/python3]
pip install .[dev]
Alternatively, you can locally install patches like this::
pip install -e .[dev]
# for usage without virtualenv, add --user
Please install pre-commit locally to run the linters before committing::
pipx install pre-commit
pre-commit install
Pull requests
-------------
When you're finished with a pull request, please:
* add a relevant test case to cpplint_unittest.py
* add a summary of what your changes do to CHANGELOG.rst
* specify the problem solved in the pull request
* make sure that your code passes the tests and lints
* don't force-push to the branch. These make the commit history messy, and we squash all commits when merging anyways.
.. _testing:
Testing
-------
You can test your changes under your local python environment by running the tests and lints below:
.. code-block:: bash
# install test requirements
pip install .[test]
# run a single test
pytest --no-cov cpplint_unittest.py -k testName
# run a single CLI integration test
pytest --no-cov cpplint_clitest.py -k testSillySample
# run all tests. you don't have to run the above tests separately
pytest
# lint the code
pylint cpplint.py
pre-commit run --all-files
Alternatively, you can run `tox` to automatically run all tests and lints. Use `-e ` followed by the python runner and version (which you must have installed) to automatically generate the testing environment and run the above tests and lints in it. For example, `tox -e py39` does the steps in Python 3.9, `tox -e py313` does the steps in Python 3.13, and `tox -e pypy3` does the steps using the latest version of the pypy interpreter.
Releasing
=========
The release process first prepares the documentation, then publishes to testpypi to verify, then releases to real pypi. Testpypi acts like real pypi, so broken releases cannot be deleted. For a typical bugfixing release, no special issue on testpypi is expected (but it's still good practice). The commands are documented below, and assume you've went through the testing steps above.
.. code-block:: bash
# prepare files for release
$EDITOR cpplint.py # increment the version
$EDITOR CHANGELOG.rst # log changes
git add cpplint.py CHANGELOG.rst
git commit -m "Releasing x.y.z"
# Build
pip install --upgrade build wheel twine
rm -rf dist
python -m build --sdist --wheel
# Test release, requires account on testpypi
twine upload --repository testpypi dist/*
# ... Check website and downloads from https://test.pypi.org/project/cpplint/
# Actual release
twine upload dist/*
git tag x.y.z
git push --tags
After releasing, it is be good practice to comment on completed GitHub issues to notify authors.
Catching up with Upstream
=========================
For maintainers, it is a regular duty to look at what cpplint changes were merged upstream and include them in this fork (though these updates happen rarely).
Checkout here and upstream google:
.. code-block:: bash
git clone git@github.com:cpplint/cpplint.git
cd cpplint
git remote add google https://github.com/google/styleguide
To incorporate google's changes:
.. code-block:: bash
git fetch google gh-pages
## Merge workflow (clean, no new commits)
git checkout develop -b updates
git merge google/gh-pages # this will have a lot of conflicts
# ... solve conflicts
git merge -- continue
## Rebase workflow (dirty, creates new commits)
git checkout -b updates FETCH_HEAD
git rebase develop # this will have a lot of conflicts, most of which can be solved with the next command (run repeatedly)
# solve conflicts with files deleted in our fork (this is idempotent and safe to be called. when cpplint.py has conflicts, it will do nothing)
git status | grep 'new file:' | awk '{print $3}' | xargs -r git rm --cached ; git status | grep 'deleted by us' | awk '{print $4}' | xargs -r git rm
git status --untracked-files=no | grep 'nothing to commit' && git rebase --skip
git push -u origin updates
# check github action
git push origin --delete updates
git rebase updates develop
git branch -D updates
git push
Setup fetching of pull requests in .git/config:
.. code-block:: bash
[remote "origin"]
url = git@github.com:cpplint/cpplint.git
fetch = +refs/heads/*:refs/remotes/origin/*
# following line should be new, fetches PRs from cpplint
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
[remote "google"]
url = https://github.com/google/styleguide
fetch = +refs/heads/*:refs/remotes/google/*
# following line should be new, fetches PRs from google/styleguides
fetch = +refs/pull/*/head:refs/remotes/google/pr/*
To compare this for with upstream (after git fetch):
.. code-block:: bash
git diff google/gh-pages:cpplint/cpplint.py develop:cpplint.py
git diff google/gh-pages:cpplint/cpplint_unittest.py develop:cpplint_unittest.py
|