diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d4a2c44 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# http://editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true +charset = utf-8 +end_of_line = lf + +[*.bat] +indent_style = tab +end_of_line = crlf + +[LICENSE] +insert_final_newline = false + +[Makefile] +indent_style = tab diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f791fd7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +# Config file for automatic testing at travis-ci.org +# This file will be regenerated if you run travis_pypi_setup.py + +language: python +python: 3.5 + +env: + - TOXENV=py35 + - TOXENV=py34 + - TOXENV=py33 + - TOXENV=py27 + - TOXENV=py26 + - TOXENV=pypy + +# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors +install: pip install -U tox + +# command to run tests, e.g. python setup.py test +script: tox + + diff --git a/AUTHORS.rst b/AUTHORS.rst new file mode 100644 index 0000000..bb02b48 --- /dev/null +++ b/AUTHORS.rst @@ -0,0 +1,13 @@ +======= +Credits +======= + +Development Lead +---------------- + +* Kenneth M. "Elf" Sternberg + +Contributors +------------ + +None yet. Why not be the first? diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..a39d1e9 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,114 @@ +.. highlight:: shell + +============ +Contributing +============ + +Contributions are welcome, and they are greatly appreciated! Every +little bit helps, and credit will always be given. + +You can contribute in many ways: + +Types of Contributions +---------------------- + +Report Bugs +~~~~~~~~~~~ + +Report bugs at https://github.com/elfsternberg/git_lint/issues. + +If you are reporting a bug, please include: + +* Your operating system name and version. +* Any details about your local setup that might be helpful in troubleshooting. +* Detailed steps to reproduce the bug. + +Fix Bugs +~~~~~~~~ + +Look through the GitHub issues for bugs. Anything tagged with "bug" +is open to whoever wants to implement it. + +Implement Features +~~~~~~~~~~~~~~~~~~ + +Look through the GitHub issues for features. Anything tagged with "feature" +is open to whoever wants to implement it. + +Write Documentation +~~~~~~~~~~~~~~~~~~~ + +Git Lint could always use more documentation, whether as part of the +official Git Lint docs, in docstrings, or even on the web in blog posts, +articles, and such. + +Submit Feedback +~~~~~~~~~~~~~~~ + +The best way to send feedback is to file an issue at https://github.com/elfsternberg/git_lint/issues. + +If you are proposing a feature: + +* Explain in detail how it would work. +* Keep the scope as narrow as possible, to make it easier to implement. +* Remember that this is a volunteer-driven project, and that contributions + are welcome :) + +Get Started! +------------ + +Ready to contribute? Here's how to set up `git_lint` for local development. + +1. Fork the `git_lint` repo on GitHub. +2. Clone your fork locally:: + + $ git clone git@github.com:your_name_here/git_lint.git + +3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: + + $ mkvirtualenv git_lint + $ cd git_lint/ + $ python setup.py develop + +4. Create a branch for local development:: + + $ git checkout -b name-of-your-bugfix-or-feature + + Now you can make your changes locally. + +5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: + + $ flake8 git_lint tests + $ python setup.py test or py.test + $ tox + + To get flake8 and tox, just pip install them into your virtualenv. + +6. Commit your changes and push your branch to GitHub:: + + $ git add . + $ git commit -m "Your detailed description of your changes." + $ git push origin name-of-your-bugfix-or-feature + +7. Submit a pull request through the GitHub website. + +Pull Request Guidelines +----------------------- + +Before you submit a pull request, check that it meets these guidelines: + +1. The pull request should include tests. +2. If the pull request adds functionality, the docs should be updated. Put + your new functionality into a function with a docstring, and add the + feature to the list in README.rst. +3. The pull request should work for Python 2.6, 2.7, 3.3, 3.4 and 3.5, and for PyPy. Check + https://travis-ci.org/elfsternberg/git_lint/pull_requests + and make sure that the tests pass for all supported Python versions. + +Tips +---- + +To run a subset of tests:: + +$ py.test tests.test_git_lint + diff --git a/HISTORY.rst b/HISTORY.rst new file mode 100644 index 0000000..dafbcd0 --- /dev/null +++ b/HISTORY.rst @@ -0,0 +1,8 @@ +======= +History +======= + +0.0.2 (2016-09-13) +------------------ + +* First release on PyPI. diff --git a/LICENSE b/LICENSE index 2c6dc4a..2241ccc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,14 @@ -The MIT License (MIT) +Copyright (c) 2016, Kenneth M. "Elf" Sternberg +All rights reserved. -Copyright (c) 2015 Ken "Elf" Mathieu Sternberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..965b2dd --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,11 @@ +include AUTHORS.rst +include CONTRIBUTING.rst +include HISTORY.rst +include LICENSE +include README.rst + +recursive-include tests * +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] + +recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1934f48 --- /dev/null +++ b/Makefile @@ -0,0 +1,86 @@ +.PHONY: clean-pyc clean-build docs clean +define BROWSER_PYSCRIPT +import os, webbrowser, sys +try: + from urllib import pathname2url +except: + from urllib.request import pathname2url + +webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) +endef +export BROWSER_PYSCRIPT +BROWSER := python -c "$$BROWSER_PYSCRIPT" + +help: + @echo "clean - remove all build, test, coverage and Python artifacts" + @echo "clean-build - remove build artifacts" + @echo "clean-pyc - remove Python file artifacts" + @echo "clean-test - remove test and coverage artifacts" + @echo "lint - check style with flake8" + @echo "test - run tests quickly with the default Python" + @echo "test-all - run tests on every Python version with tox" + @echo "coverage - check code coverage quickly with the default Python" + @echo "docs - generate Sphinx HTML documentation, including API docs" + @echo "release - package and upload a release" + @echo "dist - package" + @echo "install - install the package to the active Python's site-packages" + +clean: clean-build clean-pyc clean-test + +clean-build: + rm -fr build/ + rm -fr dist/ + rm -fr .eggs/ + find . -name '*.egg-info' -exec rm -fr {} + + find . -name '*.egg' -exec rm -f {} + + +clean-pyc: + find . -name '*.pyc' -exec rm -f {} + + find . -name '*.pyo' -exec rm -f {} + + find . -name '*~' -exec rm -f {} + + find . -name '__pycache__' -exec rm -fr {} + + +clean-test: + rm -fr .tox/ + rm -f .coverage + rm -fr htmlcov/ + +lint: + flake8 git_lint tests + +test: +py.test + + +test-all: + tox + +coverage: +coverage run --source git_lint py.test + + coverage report -m + coverage html + $(BROWSER) htmlcov/index.html + +docs: + rm -f docs/git_lint.rst + rm -f docs/modules.rst + sphinx-apidoc -o docs/ git_lint + $(MAKE) -C docs clean + $(MAKE) -C docs html + $(BROWSER) docs/_build/html/index.html + +servedocs: docs + watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . + +release: clean + python setup.py sdist upload + python setup.py bdist_wheel upload + +dist: clean + python setup.py sdist + python setup.py bdist_wheel + ls -l dist + +install: clean + python setup.py install diff --git a/README.md b/README.md deleted file mode 100644 index 1f676a2..0000000 --- a/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# pre-commit - -This program is a git pre-commit hook that runs an arbitrary set of -syntax, style, and complexity checks against files about to be checked -in. - -pre-commit is a git-hook; you install it into your project's .git -directory in .git/hooks and make it executable. It will run every time -you attempt to commit a collection of files, running the configured list -of linters against those files, and will terminate the check-in if any -of the files fails. - -pre-commit uses the `git-stash` command to temporarily store any changes -you may have made between your `git-add` and your `git-commit`; it -therefore checks against your *staged* files, not your *workspace* -files. Most hooks do the wrong thing and assume your stage and -workspace are the same. This is not necessarily so. This has the -unfortunate side-effect of touching every file if things should fail, -which may confuse your IDE. I haven't quite figured out how to deal -with that. - -pre-commit is written in Hy, a Lisp-like dialect of Python. I find Hy's -support for "cond", complex anonymous functions, and complex return -values highly appealing. The UTF-8 handling in this script means it is -compatible only with Hy running atop Python3. - -pre-commit is based on the pre-commit recommendations in Steve Pulec's -"Why you need a git-hook and why most are wrong" available at: -http://css.dzone.com/articles/why-your-need-git-pre-commit The changes -I've made reflect a different set of needs, different possible ways of -receiving error conditions, and a slightly nicer output. - -If, while installing this, you encounter a problem, you must return your -git repository to its original pre-stash state. Learn to use the -following commands correctly: - -`git stash list` - -`git stash pop` - diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..36647d3 --- /dev/null +++ b/README.rst @@ -0,0 +1,56 @@ +=============================== +Git Lint +=============================== + +A git command that automatically runs identifiable linters against +changed files in current repository or staging. + +* Free software: MIT license + +**Git Lint** runs a configurable set of syntax, style, and complexity +checkers against changed files in your current working directory or +staging area. It can be configured to work with any `lint` command. +Some commands may require shell wrappers. + +Features +-------- + +* Highly configurable - configuration files, both for git-lint and + individual linters, can be global or per-project. + +* Only checks what has been changed, but this can be overriden from the + command line. + +* For some linters, can lint both full-files and or only the parts that + have changed. + +* Can be used directly as a pre-commit hook, to ensure you personally + don't check in anything broken. + + * Used this way, it checks the *staging* area, not your workspace. + + * When using the staging area, it stashes your current work. Upon + restoration of your workspace, it ensures the timestamps are the + same, so as not to confuse your build system or IDE. + +Credits +------- + +The completion of this project was graciously sponsored by my employer, +Splunk . + +Disclaimer +---------- + +This software, including provided configuration and documentation +materials, is provided "as is" without any warranties, including any +implied warranties of merchantability, fitness, performance, or quality. +In no event shall the author or sponsor be liable for any special, +direct, indirect, or consequential damages or any damages whatsoever +resulting from loss of use, data or profits, whether in an action of +contract, negligence or other tortious action, arising out of or in +connection with the use or performance of this software. Each user of +this program Each user of the program will agree and understand, and be +deemed to have agreed and understood, that there is no warranty +whatsoever for the program and, accordingly, the entire risk arising +from or otherwise connected with the program is assumed by the user. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..5b71480 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +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 " singlehtml to make a single large HTML file" + @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 " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @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." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +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/git_lint.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/git_lint.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/git_lint" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/git_lint" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +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." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/authors.rst b/docs/authors.rst new file mode 100644 index 0000000..e122f91 --- /dev/null +++ b/docs/authors.rst @@ -0,0 +1 @@ +.. include:: ../AUTHORS.rst diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..f032372 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# git_lint documentation build configuration file, created by +# sphinx-quickstart on Tue Jul 9 22:26:36 2013. +# +# 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 +import 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.insert(0, os.path.abspath('.')) + +# Get the project root dir, which is the parent dir of this +cwd = os.getcwd() +project_root = os.path.dirname(cwd) + +# Insert the project root dir as the first element in the PYTHONPATH. +# This lets us ensure that the source package is imported, and that its +# version is used. +sys.path.insert(0, project_root) + +import git_lint + +# -- General configuration --------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] + +# 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-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Git Lint' +copyright = u'2016, Kenneth M. "Elf" Sternberg' + +# 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 = git_lint.__version__ +# The full version, including alpha/beta/rc tags. +release = git_lint.__version__ + +# 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 patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_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 = [] + +# If true, keep warnings as "system message" paragraphs in the built +# documents. +#keep_warnings = False + + +# -- Options for HTML output ------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# 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_domain_indices = 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, "Created using Sphinx" is shown in the HTML footer. +# Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. +# Default is True. +#html_show_copyright = 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 = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'git_lintdoc' + + +# -- Options for LaTeX output ------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + #'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass +# [howto/manual]). +latex_documents = [ + ('index', 'git_lint.tex', + u'Git Lint Documentation', + u'Kenneth M. "Elf" Sternberg', '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 + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output ------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'git_lint', + u'Git Lint Documentation', + [u'Kenneth M. "Elf" Sternberg'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ---------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'git_lint', + u'Git Lint Documentation', + u'Kenneth M. "Elf" Sternberg', + 'git_lint', + 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..e582053 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1 @@ +.. include:: ../CONTRIBUTING.rst diff --git a/docs/history.rst b/docs/history.rst new file mode 100644 index 0000000..2506499 --- /dev/null +++ b/docs/history.rst @@ -0,0 +1 @@ +.. include:: ../HISTORY.rst diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..6375eae --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,27 @@ +.. git_lint documentation master file, created by + sphinx-quickstart on Tue Jul 9 22:26:36 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Git Lint's documentation! +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + readme + installation + usage + contributing + authors + history + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..ad3dfdc --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,53 @@ +.. highlight:: shell + +============ +Installation +============ + + +Stable release +-------------- + +To install Git Lint, run this command in your terminal: + +.. code-block:: console + + $ pip install git_lint + +If you don't have `pip`_ installed, this `Python installation guide`_ can guide +you through the process. + +.. _pip: https://pip.pypa.io +.. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/ + + +From sources +------------ + +The sources for Git Lint can be downloaded from the `Github repo`_. + +You can either clone the public repository: + +.. code-block:: console + + $ git clone git://github.com/elfsternberg/git_lint + +Or download the `tarball`_: + +.. code-block:: console + + $ curl -OL https://github.com/elfsternberg/git_lint/tarball/master + +Once you have a copy of the source, you can install it with: + +.. code-block:: console + + $ python setup.py install + +.. _Github repo: https://github.com/elfsternberg/git_lint +.. _tarball: https://github.com/elfsternberg/git_lint/tarball/master + +Once installed, you may run the 'git lint --make-config' command, which +will generate a simple configuration file. You may install this either +in your home directory as ``.git-lint.conf`` or in your project's git +directory as ``.git/lint/git-lint.conf`` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..92284a2 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :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. singlehtml to make a single large HTML file + 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. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\git_lint.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\git_lint.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/readme.rst b/docs/readme.rst new file mode 100644 index 0000000..72a3355 --- /dev/null +++ b/docs/readme.rst @@ -0,0 +1 @@ +.. include:: ../README.rst diff --git a/docs/usage.rst b/docs/usage.rst new file mode 100644 index 0000000..e45f86d --- /dev/null +++ b/docs/usage.rst @@ -0,0 +1,58 @@ +===== +Usage +===== + +Command Line +------------ + +.. contents:: + +git lint [options] [filenames] + +Options +------- + +``-h`` ``--help`` + Help + +``-v`` ``--version`` + Version info + +``-c`` ``--config`` + Specify config file (default: ``$GIT_DIR/.git/git_lint/config``) + +``-w`` ``--workspace`` + Check workspace [default] + +``-s`` ``--staging`` + Check files in the staging area (useful as a pre-commit hook) + +``-a`` ``--all`` + Check all files in repository, not just changed files + +``-b`` ``--base`` + Run checks from your repository's root directory. By default, + ``git-lint`` only runs from the current working directory. + +``-o`` ``--only`` + Run only specific linters, skipping all others + +``-e`` ``--exclude`` + Exclude specific linters, running all others + + +As a pre-commit hook +-------------------- + + #!/usr/bin/env python + import git_lint + git_lint.run_precommit(staging = True, timestamps = True) + +Install this file in your project's ``.git/hooks/pre-commit``, and set +the file's executable flag to ``true``: + + chmod +x pre-commit + +Please see the :ref:`api` for more details on options taken by the +``run_precommit()`` and ``run_gitlint`` commands. + diff --git a/git_lint/__init__.py b/git_lint/__init__.py new file mode 100644 index 0000000..c763072 --- /dev/null +++ b/git_lint/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +__author__ = 'Kenneth M. "Elf" Sternberg' +__email__ = 'elf.sternberg@gmail.com' +__version__ = '0.0.2' diff --git a/git_lint/git_lint.py b/git_lint/git_lint.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/git_lint/git_lint.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/pre-commit b/git_lint_src/git-lint.hy old mode 100755 new mode 100644 similarity index 62% rename from pre-commit rename to git_lint_src/git-lint.hy index ad4c295..3304421 --- a/pre-commit +++ b/git_lint_src/git-lint.hy @@ -1,14 +1,67 @@ #!/usr/bin/env hy - +(import os re subprocess sys gettext) (def *version* "0.0.2") -(import os re subprocess sys) +(def _ gettext.gettext) -; pccs (pre-commit configs) should be a directory under your .git -; where you store the RCs for your various linters. If you want to -; use a global one, you'll have to edit the configuration entries -; below. +; 0: Short opt, 1: long opt, 2: takes argument, 3: help text +(def optlist [["o" "only" true (_ "A comma-separated list of only those linters to run") ["x"]] + ["x" "exclude" true (_ "A comma-separated list of linters to skip") []] + ["b" "base" false (_ "Check all changed files in the repository, not just those in the current directory.") []] + ["a" "all" false (_ "Scan all files in the repository, not just those that have changed.")] + ["w" "workspace" false (_ "Scan the workspace") ["s"]] + ["s" "staging" false (_ "Scan the staging area (pre-commit).") []] + ["g" "changes" false (_ "Report lint failures only for diff'd sections") ["l"]] + ["l" "complete" false (_ "Report lint failures for all files") []] + ["c" "config" true (_ "Path to config file") []] + ["h" "help" false (_ "This help message") []] + ["v" "version" false (_"Version information") []]]) + +; Given a set of command-line arguments, compare that to a mapped +; version of the optlist and return a canonicalized dictionary of all +; the arguments that have been set. For example "-c" and "--config" +; will both be mapped to "config". + +; Given a prefix of one or two dashes and a position in the above +; array, creates a function to map either the short or long option +; to the option name. + +(defn make-opt-assoc [prefix pos] + (fn [acc it] (assoc acc (+ prefix (get it pos)) (get it 1)) acc)) + +; Using the above, create a full map of all arguments, then return a +; function ready to look up any argument and return the option name. + +(defn make-options-rationalizer [optlist] + (let [ + [short-opt-assoc (make-opt-assoc "-" 0)] + [long-opt-assoc (make-opt-assoc "--" 1)] + [fullset + (ap-reduce (-> (short-opt-assoc acc it) + (long-opt-assoc it)) optlist {})]] + (fn [acc it] (do (assoc acc (get fullset (get it 0)) (get it 1)) acc)))) + + + + +(defn print-version [] + (print (.format "git-lint (hy version {})" *version*)) + (print "Copyright (c) 2008, 2014 Kenneth M. \"Elf\" Sternberg ") + (sys.exit)) + +(defn print-help [] + (print "Usage: git lint [options] [filename]") + (ap-each optlist (print (.format " -{} --{} {}" (get it 0) (get it 1) (get it 3)))) + (sys.exit)) + +; `lint` should be a directory under your .git where you store the RCs +; for your various linters. If you want to use a global one, you'll +; have to edit the configuration entries below. + +(def *config-path* + + + (os.path.join (.get os.environ "GIT_DIR" "./.git") "lint")) -(def *config-path* (os.path.join (.get os.environ "GIT_DIR" "./.git") "pccs")) (def *git-modified-pattern* (.compile re "^[MA]\s+(?P.*)$")) (def *checks* @@ -179,3 +232,24 @@ (defmain [&rest args] (let [[scan-all-files (and (> (len args) 1) (= (get args 2) "--all-files"))]] (sys.exit (int (run-checks-for scan-all-files (get-head-tag)))))) + +(defmain [&rest args] + (try + (let [[optstringsshort + (string.join (ap-map (+ (. it [0]) (cond [(. it [2]) ":"] [true ""])) optlist) "")] + [optstringslong + (list (ap-map (+ (. it [1]) (cond [(. it [2]) "="] [true ""])) optlist))] + [(, opt arg) + (getopt.getopt (slice args 1) optstringsshort optstringslong)] + [rationalize-options + (make-options-rationalizer optlist)] + [options + (sanify-options (ap-reduce (rationalize-options acc it) opt {}))]] + + + (cond [(.has_key options "help") (print-help)] + [(.has_key options "version") (print-version)] + [true (suggest options)])) + (catch [err getopt.GetoptError] + (print (str err)) + (print-help)))) diff --git a/pre-commit.py b/pre-commit.py deleted file mode 100644 index fb2b510..0000000 --- a/pre-commit.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env python - -# This Python file is a hand-edited version of the Hy version. It has -# the exact same functionality, but I recommend using the Hy version -# if you can, as it's the one I'm actively maintaining. - -VERSION = '0.0.2' -import os -import re -import subprocess -import sys - -CONFIG_PATH = os.path.join(os.environ.get('GIT_DIR', './.git'), 'pccs') -GIT_MODIFIED_PATTERN = re.compile('^[MA]\\s+(?P.*)$') -CHECKS = [ - { - 'output': 'Running Jshint...', - 'command': 'jshint -c {config_path}/jshint.rc {filename}', - 'match_files': ['.*\\.js$'], - 'print_filename': False, - 'error_condition': 'error' - }, - { - 'output': 'Running Coffeelint...', - 'command': 'coffeelint {filename}', - 'match_files': ['.*\\.coffee$'], - 'print_filename': False, - 'error_condition': 'error' - }, - { - 'output': 'Running JSCS...', - 'command': 'jscs -c {config_path}/jscs.rc {filename}', - 'match_files': ['.*\\.js$'], - 'print_filename': False, - 'error_condition': 'error' - }, - { - 'output': 'Running pep8...', - 'command': 'pep8 -r --ignore=E501,W293,W391 {filename}', - 'match_files': ['.*\\.py$'], - 'print_filename': False, - 'error_condition': 'error' - }, - { - 'output': 'Running xmllint...', - 'command': 'xmllint {filename}', - 'match_files': ['.*\\.xml'], - 'print_filename': False, - 'error_condition': 'error' - } -] - - -def flatten(alist): - if isinstance(alist, list): - if len(alist) == 0: - return [] - first, rest = alist[0], alist[1:] - return flatten(first) + flatten(rest) - return [alist] - - -def get_git_response(cmd): - fullcmd = (['git'] + cmd) - process = subprocess.Popen(fullcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (out, err) = process.communicate() - (out, err) - return (out, err, process.returncode) - - -def run_git_command(cmd): - fullcmd = (['git'] + cmd) - return subprocess.call(fullcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - -def get_shell_response(fullcmd): - process = subprocess.Popen(fullcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - (out, err) = process.communicate() - (out, err) - return (out, err, process.returncode) - - -def derive_max_code(code_pairs): - def find_max_code(m, i): - if abs(i[0]) > abs(m): - return i[0] - return m - return reduce(find_max_code, code_pairs, 0) - - -def lmap(pred, iterable): - return list(map(pred, iterable)) - - -def derive_message_bodies(code_pairs): - def get_first(i): - return i[1] - return lmap(get_first, code_pairs) - - -def encode_shell_messages(prefix, messages): - def encode(line): - return '{}{}'.format(prefix, line.decode('utf-8')) - return lmap(encode, messages.splitlines()) - - -def run_external_checker(filename, check): - cmd = check['command'].format(filename=filename, config_path=CONFIG_PATH) - (out, err, returncode) = get_shell_response(cmd) - if ((out and (check.get('error_condition', 'error') == 'output')) or err or (not (returncode == 0))): - prefix = ('\t{}:'.format(filename) if check['print_filename'] else '\t') - output = (encode_shell_messages(prefix, out) + (encode_shell_messages(prefix, err) if err else [])) - return [(returncode or 1), output] - return [0, []] - - -def matches_file(filename, match_files): - def match_one(match_file): - return re.compile(match_file).match(filename) - return any(map(match_one, match_files)) - - -def check_scan_wanted(filename, check): - if (('match_files' in check) and (not matches_file(filename, check['match_files']))): - return False - if (('ignore_files' in check) and matches_file(filename, check['ignore_files'])): - return False - return True - - -def check_files(filenames, check): - def scan_wanted(filename): - return check_scan_wanted(filename, check) - filenames_to_check = filter(scan_wanted, filenames) - - def external_check(filename): - return run_external_checker(filename, check) - - results_of_checks = lmap(external_check, filenames_to_check) - messages = ([check['output']] + derive_message_bodies(results_of_checks)) - return [derive_max_code(results_of_checks), messages] - - -def gather_all_filenames(): - def build_filenames(filenames): - def make_path(f): - return os.path.join(filenames[0], f) - return map(make_path, filenames[2]) - return list(flatten([build_filenames(o) for o in os.walk('.')])) - - -def gather_staged_filenames(against): - (out, err, returncode) = get_git_response(['diff-index', '--name-status', against]) - (out, err, returncode) - lines = out.splitlines() - - def matcher(line): - return GIT_MODIFIED_PATTERN.match(line.decode('utf-8')) - - return [s for s in [match.group('name') - for match in [matcher(l) for l in lines] if match] - if not (s == '')] - - -def run_checks_for(scan_all_files, against): - run_git_command(['stash', '--keep-index']) - filenames_to_scan = (gather_all_filenames() if scan_all_files else gather_staged_filenames(against)) - - def run_check(check): - return check_files(filenames_to_scan, check) - results_of_scan = lmap(run_check, CHECKS) - exit_code = derive_max_code(results_of_scan) - messages = flatten(derive_message_bodies(results_of_scan)) - for line in messages: - print(line) - run_git_command(['reset', '--hard']) - run_git_command(['stash', 'pop', '--quiet', '--index']) - return exit_code - - -def get_head_tag(): - empty_repository_hash = '4b825dc642cb6eb9a060e54bf8d69288fbee4904' - (out, err, returncode) = get_git_response(['rev-parse', '--verify HEAD']) - (out, err, returncode) - return (empty_repository_hash if err else 'HEAD') - - -def main(*args): - scan_all_files = ((len(args) > 1) and (args[2] == u'--all-files')) - return int(run_checks_for(scan_all_files, get_head_tag())) - -if (__name__ == u'__main__'): - import sys - sys.exit(main(*sys.argv)) diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..649c085 --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,9 @@ +bumpversion==0.5.3 +wheel==0.23.0 +watchdog==0.8.3 +flake8==2.4.1 +tox==2.1.1 +coverage==4.0 +Sphinx==1.3.1 + +pytest==2.8.3 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..cb3dba8 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,18 @@ +[bumpversion] +current_version = 0.0.2 +commit = True +tag = True + +[bumpversion:file:setup.py] +search = version='{current_version}' +replace = version='{new_version}' + +[bumpversion:file:git_lint/__init__.py] +search = __version__ = '{current_version}' +replace = __version__ = '{new_version}' + +[wheel] +universal = 1 + +[flake8] +exclude = docs diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..bd4e95a --- /dev/null +++ b/setup.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + + +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + + +with open('README.rst') as readme_file: + readme = readme_file.read() + +with open('HISTORY.rst') as history_file: + history = history_file.read() + +requirements = [ + # TODO: put package requirements here +] + +test_requirements = [ + # TODO: put package test requirements here +] + +setup( + name='git_lint', + version='0.0.2', + description="A git command to lint everything in your workspace (or stage) that was changed since the last commit.", + long_description=readme + '\n\n' + history, + author="Kenneth M. "Elf" Sternberg", + author_email='elf.sternberg@gmail.com', + url='https://github.com/elfsternberg/git_lint', + packages=[ + 'git_lint', + ], + package_dir={'git_lint': + 'git_lint'}, + include_package_data=True, + install_requires=requirements, + license="ISCL", + zip_safe=False, + keywords='git_lint', + classifiers=[ + 'Development Status :: 2 - Pre-Alpha', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: ISC License (ISCL)', + 'Natural Language :: English', + "Programming Language :: Python :: 2", + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + ], + test_suite='tests', + tests_require=test_requirements +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/test_git_lint.py b/tests/test_git_lint.py new file mode 100644 index 0000000..bfac493 --- /dev/null +++ b/tests/test_git_lint.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +test_git_lint +---------------------------------- + +Tests for `git_lint` module. +""" + +import pytest + + +from git_lint import git_lint + +class TestGit_lint(object): + + @classmethod + def setup_class(cls): + pass + + def test_something(self): + pass + + @classmethod + def teardown_class(cls): + pass + diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..eb674fd --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[tox] +envlist = py26, py27, py33, py34, py35 + +[testenv] +setenv = + PYTHONPATH = {toxinidir}:{toxinidir}/git_lint +deps = + -r{toxinidir}/requirements_dev.txt +commands = + py.test --basetemp={envtmpdir} + + +; If you want to make tox run the tests with the same versions, create a +; requirements.txt with the pinned versions and uncomment the following lines: +; deps = +; -r{toxinidir}/requirements.txt