Compare commits
	
		
			1 Commits
		
	
	
		
			master
			...
			inotify-ca
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 739075d2df | 
|  | @ -63,9 +63,3 @@ match = .json | ||||||
| print = False | print = False | ||||||
| condition = error | condition = error | ||||||
| 
 | 
 | ||||||
| [readability] |  | ||||||
| output = Running Text Style Check |  | ||||||
| match = .rst |  | ||||||
| command = git-lint-style --min=6 --max=12 |  | ||||||
| print = False |  | ||||||
| condition = error |  | ||||||
|  |  | ||||||
|  | @ -10,4 +10,4 @@ Development Lead | ||||||
| Contributors | Contributors | ||||||
| ------------ | ------------ | ||||||
| 
 | 
 | ||||||
| * Tino de Bruijn <work@tino.io> | None yet. Why not be the first? | ||||||
|  |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| GitLint is a git command to automatically run a suite of pre-defined linters. |  | ||||||
|  | @ -8,6 +8,4 @@ recursive-include tests * | ||||||
| recursive-exclude * __pycache__ | recursive-exclude * __pycache__ | ||||||
| recursive-exclude * *.py[co] | recursive-exclude * *.py[co] | ||||||
| 
 | 
 | ||||||
| recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif *.1 | recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif | ||||||
| include docs/_build/man/git-lint.1 |  | ||||||
| include bin/pre-commit bin/git-lint-style |  | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										10
									
								
								Makefile
								
								
								
								
							|  | @ -12,7 +12,6 @@ export BROWSER_PYSCRIPT | ||||||
| BROWSER := python -c "$$BROWSER_PYSCRIPT" | BROWSER := python -c "$$BROWSER_PYSCRIPT" | ||||||
| 
 | 
 | ||||||
| help: | help: | ||||||
| 	@echo "all - local build including docs" |  | ||||||
| 	@echo "clean - remove all build, test, coverage and Python artifacts" | 	@echo "clean - remove all build, test, coverage and Python artifacts" | ||||||
| 	@echo "clean-build - remove build artifacts" | 	@echo "clean-build - remove build artifacts" | ||||||
| 	@echo "clean-pyc - remove Python file artifacts" | 	@echo "clean-pyc - remove Python file artifacts" | ||||||
|  | @ -22,14 +21,10 @@ help: | ||||||
| 	@echo "test-all - run tests on every Python version with tox" | 	@echo "test-all - run tests on every Python version with tox" | ||||||
| 	@echo "coverage - check code coverage quickly with the default Python" | 	@echo "coverage - check code coverage quickly with the default Python" | ||||||
| 	@echo "docs - generate Sphinx HTML documentation, including API docs" | 	@echo "docs - generate Sphinx HTML documentation, including API docs" | ||||||
| 	@echo "docsbrowse - generate Sphinx HTML documentation and start browser" |  | ||||||
| 	@echo "release - package and upload a release" | 	@echo "release - package and upload a release" | ||||||
| 	@echo "dist - package" | 	@echo "dist - package" | ||||||
| 	@echo "install - install the package to the active Python's site-packages" | 	@echo "install - install the package to the active Python's site-packages" | ||||||
| 
 | 
 | ||||||
| all: docs |  | ||||||
| 	python setup.py build |  | ||||||
| 
 |  | ||||||
| clean: clean-build clean-pyc clean-test | clean: clean-build clean-pyc clean-test | ||||||
| 
 | 
 | ||||||
| clean-build: | clean-build: | ||||||
|  | @ -72,9 +67,6 @@ docs: | ||||||
| 	sphinx-apidoc -o docs/ git_lint | 	sphinx-apidoc -o docs/ git_lint | ||||||
| 	$(MAKE) -C docs clean | 	$(MAKE) -C docs clean | ||||||
| 	$(MAKE) -C docs html | 	$(MAKE) -C docs html | ||||||
| 	$(MAKE) -C docs man |  | ||||||
| 
 |  | ||||||
| docbrowse: docs |  | ||||||
| 	$(BROWSER) docs/_build/html/index.html | 	$(BROWSER) docs/_build/html/index.html | ||||||
| 
 | 
 | ||||||
| servedocs: docs | servedocs: docs | ||||||
|  | @ -90,4 +82,4 @@ dist: clean | ||||||
| 	ls -l dist | 	ls -l dist | ||||||
| 
 | 
 | ||||||
| install: clean | install: clean | ||||||
| 	python setup.py install --prefix=/usr/local | 	python setup.py install | ||||||
|  |  | ||||||
							
								
								
									
										79
									
								
								README.rst
								
								
								
								
							
							
						
						
									
										79
									
								
								README.rst
								
								
								
								
							|  | @ -1,65 +1,23 @@ | ||||||
| =============================== | =============================== | ||||||
| Git Lint: README | Git Lint | ||||||
| =============================== | =============================== | ||||||
| 
 | 
 | ||||||
| A git command that automatically runs identifiable linters against | A git command that automatically runs identifiable linters against | ||||||
| changed files in your current git repository or staging area. | changed files in current repository or staging. | ||||||
| 
 | 
 | ||||||
| * Free software: MIT license | * Free software: MIT license | ||||||
| 
 | 
 | ||||||
| **Git Lint** runs a configurable set of syntax, style, and complexity | **Git Lint** runs a configurable set of syntax, style, and complexity | ||||||
| checkers against changed files in your current working directory or | checkers against changed files in your current working directory or | ||||||
| staging area.  It can be configured to work with any `lint`-like | staging area.  It can be configured to work with any `lint` command. | ||||||
| command.  Some commands may require shell wrappers. | Some commands may require shell wrappers. | ||||||
| 
 | 
 | ||||||
| While it may be possible to create a custom lint command in your npm, | While it may be possible to create a custom lint command in your npm, | ||||||
| grunt, Make, CMake, or whatever, the fact is we all use a VCS, and most | grunt, Make, CMake, or whatever, the fact is we all use a VCS, and | ||||||
| of us use git.  Having a centralized repository for what we want checked | most of us use git.  Having a centralized repository for what we want | ||||||
| and how we want it checked, associated with git (and by extension, as a | checked and how we want it checked, associated with git (and by | ||||||
| pre-commit hook), that can be run at any time for any reason. | extension, as a pre-commit hook), that can be run at any time for any | ||||||
| 
 | reason. | ||||||
| Usage |  | ||||||
| ----- |  | ||||||
| 
 |  | ||||||
| To lint only what's changed recently in your current working directory: |  | ||||||
|     `git lint` |  | ||||||
| 
 |  | ||||||
| To lint everything, changed or otherwise, from the current directory down: |  | ||||||
|     `git lint -a` |  | ||||||
| 
 |  | ||||||
| To lint what's changed from the repo's base: |  | ||||||
|     `git lint -b` |  | ||||||
| 
 |  | ||||||
| To lint what's in your staging directory: |  | ||||||
|     `git lint -s` |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Documentation |  | ||||||
| ------------- |  | ||||||
| 
 |  | ||||||
| Complete documentation for the project is available in the docs directory, or at `Git |  | ||||||
| Linter Docs <https://elfsternberg.github.io/git-linter/index.html>`_. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Install |  | ||||||
| ------- |  | ||||||
| 
 |  | ||||||
| This *ought* to work: |  | ||||||
| 
 |  | ||||||
|     `pip install git-linter` |  | ||||||
| 
 |  | ||||||
| You will need to copy the .git-lint configuration file to either your |  | ||||||
| home directory or the repo`s base directory.  Edit the configuration |  | ||||||
| file as needed.  You will also need any linters that you plan on |  | ||||||
| running. |  | ||||||
| 
 |  | ||||||
| As git-linter is still mostly alpha code, it might be better to install |  | ||||||
| from source: |  | ||||||
| 
 |  | ||||||
|     `` |  | ||||||
|     git clone https://github.com/elfsternberg/git-linter |  | ||||||
|     python setup.py install |  | ||||||
|     `` |  | ||||||
| 
 | 
 | ||||||
| Features | Features | ||||||
| -------- | -------- | ||||||
|  | @ -79,22 +37,11 @@ Features | ||||||
|     restoration of your workspace, it ensures the timestamps are the |     restoration of your workspace, it ensures the timestamps are the | ||||||
|     same, so as not to confuse your build system or IDE. |     same, so as not to confuse your build system or IDE. | ||||||
| 
 | 
 | ||||||
|  | Credits | ||||||
|  | ------- | ||||||
| 
 | 
 | ||||||
| Acknowledgements | The completion of this project was graciously sponsored by my employer, | ||||||
| ---------------- | Splunk <http://splunk.com>. | ||||||
| 
 |  | ||||||
| `Git lint` started life as a simple pre-commit hook.  Most of the changes since were |  | ||||||
| inspired by Steve Pulec's `Why You Need a Git Pre-Commit Hook and Why Most Are Wrong <https://dzone.com/articles/why-your-need-git-pre-commit>`_, as well as just my own needs |  | ||||||
| as a software developer. |  | ||||||
| 
 |  | ||||||
| To do |  | ||||||
| ----- |  | ||||||
| 
 |  | ||||||
| * The '-q' and '--quiet' arguments do not work. |  | ||||||
| * Ought to be able to silence the "no linter found" message. |  | ||||||
| * Ought to be able to configure '-q' and '--silence' commands in .git-lint/config file. |  | ||||||
| * Ought to be able to override config file for above. |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| Disclaimer | Disclaimer | ||||||
| ---------- | ---------- | ||||||
|  |  | ||||||
|  | @ -46,10 +46,6 @@ def main(*args): | ||||||
|         print(error) |         print(error) | ||||||
|         return returncode |         return returncode | ||||||
|     kincaid = re.search(r'Kincaid:\s*([\d\.]+)', values, re.MULTILINE) |     kincaid = re.search(r'Kincaid:\s*([\d\.]+)', values, re.MULTILINE) | ||||||
| 
 |  | ||||||
|     # Assumes an uncheckable issue, like an empty RST.  Not unusual. |  | ||||||
|     if not kincaid:  |  | ||||||
|         return 0 |  | ||||||
|     val = float(kincaid.group(1)) |     val = float(kincaid.group(1)) | ||||||
| 
 | 
 | ||||||
|     msg = "" |     msg = "" | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| #!/usr/bin/env python | #!/usr/bin/env python | ||||||
| from git_lint.git_lint import load_config, run_linters, git_base | from git_lint import load_config, run_linters, git_base | ||||||
| from git_lint.reporters import print_report |  | ||||||
| 
 | 
 | ||||||
| import gettext | import gettext | ||||||
| _ = gettext.gettext | _ = gettext.gettext | ||||||
|  | @ -21,14 +20,14 @@ def main(*args): | ||||||
|      unlintable_filenames, |      unlintable_filenames, | ||||||
|      cant_lint_filenames, |      cant_lint_filenames, | ||||||
|      broken_linter_names, |      broken_linter_names, | ||||||
|      unfindable_filenames) = run_linters(pre_commit_options, config) |      unfindable_filenames) = run_linters(options, config) | ||||||
|      |      | ||||||
|     print_report(results, |     print_report(results, | ||||||
|                  unlintable_filenames, |                  unlintable_filenames, | ||||||
|                  cant_lint_filenames, |                  cant_lint_filenames, | ||||||
|                  broken_linter_names, |                  broken_linter_names, | ||||||
|                  unfindable_filenames, |                  unfindable_filenames, | ||||||
|                  pre_commit_options) |                  options) | ||||||
| 
 | 
 | ||||||
|     if not len(results): |     if not len(results): | ||||||
|         return 0 |         return 0 | ||||||
|  |  | ||||||
|  | @ -14,19 +14,12 @@ | ||||||
|     Scan the workspace [default] |     Scan the workspace [default] | ||||||
| **-s, --staging** | **-s, --staging** | ||||||
|     Scan the staging area (useful for pre-commit). |     Scan the staging area (useful for pre-commit). | ||||||
| **-c <path>, --config=<path>** | **-c** <path>, --config**=<path>  Path to config file | ||||||
|     Path to config file |  | ||||||
| **-t, --bylinter** |  | ||||||
|     Group reports by linter first as they appear in the config file [default] |  | ||||||
| **-f, --byfile** |  | ||||||
|     Group reports by file first, linter second |  | ||||||
| **-d, --dryrun** | **-d, --dryrun** | ||||||
|     Report what git-lint would do, but don't actually do anything. |     Report what git-lint would do, but don't actually do anything. | ||||||
| **-q, --quiet** | **-q, --quiet** | ||||||
|     Produce a short report of file that failed to pass. |     Produce a short report of files that failed to pass. | ||||||
| **-h, --help** | **-h, --help** | ||||||
|     Print a short help message |     Print a short help message | ||||||
| **-V, --verbose** |  | ||||||
|     Print a slightly more verbose long report |  | ||||||
| **-v, --version** | **-v, --version** | ||||||
|     Print version information |     Print version information | ||||||
|  |  | ||||||
							
								
								
									
										92
									
								
								docs/conf.py
								
								
								
								
							
							
						
						
									
										92
									
								
								docs/conf.py
								
								
								
								
							|  | @ -20,7 +20,7 @@ import os | ||||||
| # directory, add these directories to sys.path here. If the directory is | # directory, add these directories to sys.path here. If the directory is | ||||||
| # relative to the documentation root, use os.path.abspath to make it | # relative to the documentation root, use os.path.abspath to make it | ||||||
| # absolute, like shown here. | # absolute, like shown here. | ||||||
| # sys.path.insert(0, os.path.abspath('.')) | #sys.path.insert(0, os.path.abspath('.')) | ||||||
| 
 | 
 | ||||||
| # Get the project root dir, which is the parent dir of this | # Get the project root dir, which is the parent dir of this | ||||||
| cwd = os.getcwd() | cwd = os.getcwd() | ||||||
|  | @ -31,12 +31,12 @@ project_root = os.path.dirname(cwd) | ||||||
| # version is used. | # version is used. | ||||||
| sys.path.insert(0, project_root) | sys.path.insert(0, project_root) | ||||||
| 
 | 
 | ||||||
| import git_lint  # noqa | import git_lint | ||||||
| 
 | 
 | ||||||
| # -- General configuration --------------------------------------------- | # -- General configuration --------------------------------------------- | ||||||
| 
 | 
 | ||||||
| # If your documentation needs a minimal Sphinx version, state it here. | # If your documentation needs a minimal Sphinx version, state it here. | ||||||
| # needs_sphinx = '1.0' | #needs_sphinx = '1.0' | ||||||
| 
 | 
 | ||||||
| # Add any Sphinx extension module names here, as strings. They can be | # Add any Sphinx extension module names here, as strings. They can be | ||||||
| # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. | ||||||
|  | @ -49,7 +49,7 @@ templates_path = ['_templates'] | ||||||
| source_suffix = '.rst' | source_suffix = '.rst' | ||||||
| 
 | 
 | ||||||
| # The encoding of source files. | # The encoding of source files. | ||||||
| # source_encoding = 'utf-8-sig' | #source_encoding = 'utf-8-sig' | ||||||
| 
 | 
 | ||||||
| # The master toctree document. | # The master toctree document. | ||||||
| master_doc = 'index' | master_doc = 'index' | ||||||
|  | @ -69,13 +69,13 @@ release = git_lint.__version__ | ||||||
| 
 | 
 | ||||||
| # The language for content autogenerated by Sphinx. Refer to documentation | # The language for content autogenerated by Sphinx. Refer to documentation | ||||||
| # for a list of supported languages. | # for a list of supported languages. | ||||||
| # language = None | #language = None | ||||||
| 
 | 
 | ||||||
| # There are two options for replacing |today|: either, you set today to | # There are two options for replacing |today|: either, you set today to | ||||||
| # some non-false value, then it is used: | # some non-false value, then it is used: | ||||||
| # today = '' | #today = '' | ||||||
| # Else, today_fmt is used as the format for a strftime call. | # Else, today_fmt is used as the format for a strftime call. | ||||||
| # today_fmt = '%B %d, %Y' | #today_fmt = '%B %d, %Y' | ||||||
| 
 | 
 | ||||||
| # List of patterns, relative to source directory, that match files and | # List of patterns, relative to source directory, that match files and | ||||||
| # directories to ignore when looking for source files. | # directories to ignore when looking for source files. | ||||||
|  | @ -83,60 +83,60 @@ exclude_patterns = ['_build'] | ||||||
| 
 | 
 | ||||||
| # The reST default role (used for this markup: `text`) to use for all | # The reST default role (used for this markup: `text`) to use for all | ||||||
| # documents. | # documents. | ||||||
| # default_role = None | #default_role = None | ||||||
| 
 | 
 | ||||||
| # If true, '()' will be appended to :func: etc. cross-reference text. | # If true, '()' will be appended to :func: etc. cross-reference text. | ||||||
| # add_function_parentheses = True | #add_function_parentheses = True | ||||||
| 
 | 
 | ||||||
| # If true, the current module name will be prepended to all description | # If true, the current module name will be prepended to all description | ||||||
| # unit titles (such as .. function::). | # unit titles (such as .. function::). | ||||||
| # add_module_names = True | #add_module_names = True | ||||||
| 
 | 
 | ||||||
| # If true, sectionauthor and moduleauthor directives will be shown in the | # If true, sectionauthor and moduleauthor directives will be shown in the | ||||||
| # output. They are ignored by default. | # output. They are ignored by default. | ||||||
| # show_authors = False | #show_authors = False | ||||||
| 
 | 
 | ||||||
| # The name of the Pygments (syntax highlighting) style to use. | # The name of the Pygments (syntax highlighting) style to use. | ||||||
| pygments_style = 'sphinx' | pygments_style = 'sphinx' | ||||||
| 
 | 
 | ||||||
| # A list of ignored prefixes for module index sorting. | # A list of ignored prefixes for module index sorting. | ||||||
| # modindex_common_prefix = [] | #modindex_common_prefix = [] | ||||||
| 
 | 
 | ||||||
| # If true, keep warnings as "system message" paragraphs in the built | # If true, keep warnings as "system message" paragraphs in the built | ||||||
| # documents. | # documents. | ||||||
| # keep_warnings = False | #keep_warnings = False | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # -- Options for HTML output ------------------------------------------- | # -- Options for HTML output ------------------------------------------- | ||||||
| 
 | 
 | ||||||
| # The theme to use for HTML and HTML Help pages.  See the documentation for | # The theme to use for HTML and HTML Help pages.  See the documentation for | ||||||
| # a list of builtin themes. | # a list of builtin themes. | ||||||
| html_theme = 'alabaster' | html_theme = 'default' | ||||||
| 
 | 
 | ||||||
| # Theme options are theme-specific and customize the look and feel of a | # 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 | # theme further.  For a list of options available for each theme, see the | ||||||
| # documentation. | # documentation. | ||||||
| # html_theme_options = {} | #html_theme_options = {} | ||||||
| 
 | 
 | ||||||
| # Add any paths that contain custom themes here, relative to this directory. | # Add any paths that contain custom themes here, relative to this directory. | ||||||
| # html_theme_path = [] | #html_theme_path = [] | ||||||
| 
 | 
 | ||||||
| # The name for this set of Sphinx documents.  If None, it defaults to | # The name for this set of Sphinx documents.  If None, it defaults to | ||||||
| # "<project> v<release> documentation". | # "<project> v<release> documentation". | ||||||
| # html_title = None | #html_title = None | ||||||
| 
 | 
 | ||||||
| # A shorter title for the navigation bar.  Default is the same as | # A shorter title for the navigation bar.  Default is the same as | ||||||
| # html_title. | # html_title. | ||||||
| # html_short_title = None | #html_short_title = None | ||||||
| 
 | 
 | ||||||
| # The name of an image file (relative to this directory) to place at the | # The name of an image file (relative to this directory) to place at the | ||||||
| # top of the sidebar. | # top of the sidebar. | ||||||
| # html_logo = None | #html_logo = None | ||||||
| 
 | 
 | ||||||
| # The name of an image file (within the static path) to use as favicon | # 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 | # of the docs.  This file should be a Windows icon file (.ico) being | ||||||
| # 16x16 or 32x32 pixels large. | # 16x16 or 32x32 pixels large. | ||||||
| # html_favicon = None | #html_favicon = None | ||||||
| 
 | 
 | ||||||
| # Add any paths that contain custom static files (such as style sheets) | # Add any paths that contain custom static files (such as style sheets) | ||||||
| # here, relative to this directory. They are copied after the builtin | # here, relative to this directory. They are copied after the builtin | ||||||
|  | @ -146,46 +146,46 @@ html_static_path = ['_static'] | ||||||
| 
 | 
 | ||||||
| # If not '', a 'Last updated on:' timestamp is inserted at every page | # If not '', a 'Last updated on:' timestamp is inserted at every page | ||||||
| # bottom, using the given strftime format. | # bottom, using the given strftime format. | ||||||
| # html_last_updated_fmt = '%b %d, %Y' | #html_last_updated_fmt = '%b %d, %Y' | ||||||
| 
 | 
 | ||||||
| # If true, SmartyPants will be used to convert quotes and dashes to | # If true, SmartyPants will be used to convert quotes and dashes to | ||||||
| # typographically correct entities. | # typographically correct entities. | ||||||
| # html_use_smartypants = True | #html_use_smartypants = True | ||||||
| 
 | 
 | ||||||
| # Custom sidebar templates, maps document names to template names. | # Custom sidebar templates, maps document names to template names. | ||||||
| # html_sidebars = {} | #html_sidebars = {} | ||||||
| 
 | 
 | ||||||
| # Additional templates that should be rendered to pages, maps page names | # Additional templates that should be rendered to pages, maps page names | ||||||
| # to template names. | # to template names. | ||||||
| # html_additional_pages = {} | #html_additional_pages = {} | ||||||
| 
 | 
 | ||||||
| # If false, no module index is generated. | # If false, no module index is generated. | ||||||
| # html_domain_indices = True | #html_domain_indices = True | ||||||
| 
 | 
 | ||||||
| # If false, no index is generated. | # If false, no index is generated. | ||||||
| # html_use_index = True | #html_use_index = True | ||||||
| 
 | 
 | ||||||
| # If true, the index is split into individual pages for each letter. | # If true, the index is split into individual pages for each letter. | ||||||
| # html_split_index = False | #html_split_index = False | ||||||
| 
 | 
 | ||||||
| # If true, links to the reST sources are added to the pages. | # If true, links to the reST sources are added to the pages. | ||||||
| # html_show_sourcelink = True | #html_show_sourcelink = True | ||||||
| 
 | 
 | ||||||
| # If true, "Created using Sphinx" is shown in the HTML footer. | # If true, "Created using Sphinx" is shown in the HTML footer. | ||||||
| # Default is True. | # Default is True. | ||||||
| # html_show_sphinx = True | #html_show_sphinx = True | ||||||
| 
 | 
 | ||||||
| # If true, "(C) Copyright ..." is shown in the HTML footer. | # If true, "(C) Copyright ..." is shown in the HTML footer. | ||||||
| # Default is True. | # Default is True. | ||||||
| # html_show_copyright = True | #html_show_copyright = True | ||||||
| 
 | 
 | ||||||
| # If true, an OpenSearch description file will be output, and all pages | # If true, an OpenSearch description file will be output, and all pages | ||||||
| # will contain a <link> tag referring to it.  The value of this option | # will contain a <link> tag referring to it.  The value of this option | ||||||
| # must be the base URL from which the finished HTML is served. | # must be the base URL from which the finished HTML is served. | ||||||
| # html_use_opensearch = '' | #html_use_opensearch = '' | ||||||
| 
 | 
 | ||||||
| # This is the file name suffix for HTML files (e.g. ".xhtml"). | # This is the file name suffix for HTML files (e.g. ".xhtml"). | ||||||
| # html_file_suffix = None | #html_file_suffix = None | ||||||
| 
 | 
 | ||||||
| # Output file base name for HTML help builder. | # Output file base name for HTML help builder. | ||||||
| htmlhelp_basename = 'git_lintdoc' | htmlhelp_basename = 'git_lintdoc' | ||||||
|  | @ -195,13 +195,13 @@ htmlhelp_basename = 'git_lintdoc' | ||||||
| 
 | 
 | ||||||
| latex_elements = { | latex_elements = { | ||||||
|     # The paper size ('letterpaper' or 'a4paper'). |     # The paper size ('letterpaper' or 'a4paper'). | ||||||
|     # 'papersize': 'letterpaper', |     #'papersize': 'letterpaper', | ||||||
| 
 | 
 | ||||||
|     # The font size ('10pt', '11pt' or '12pt'). |     # The font size ('10pt', '11pt' or '12pt'). | ||||||
|     # 'pointsize': '10pt', |     #'pointsize': '10pt', | ||||||
| 
 | 
 | ||||||
|     # Additional stuff for the LaTeX preamble. |     # Additional stuff for the LaTeX preamble. | ||||||
|     # 'preamble': '', |     #'preamble': '', | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| # Grouping the document tree into LaTeX files. List of tuples | # Grouping the document tree into LaTeX files. List of tuples | ||||||
|  | @ -215,23 +215,23 @@ latex_documents = [ | ||||||
| 
 | 
 | ||||||
| # The name of an image file (relative to this directory) to place at | # The name of an image file (relative to this directory) to place at | ||||||
| # the top of the title page. | # the top of the title page. | ||||||
| # latex_logo = None | #latex_logo = None | ||||||
| 
 | 
 | ||||||
| # For "manual" documents, if this is true, then toplevel headings | # For "manual" documents, if this is true, then toplevel headings | ||||||
| # are parts, not chapters. | # are parts, not chapters. | ||||||
| # latex_use_parts = False | #latex_use_parts = False | ||||||
| 
 | 
 | ||||||
| # If true, show page references after internal links. | # If true, show page references after internal links. | ||||||
| # latex_show_pagerefs = False | #latex_show_pagerefs = False | ||||||
| 
 | 
 | ||||||
| # If true, show URL addresses after external links. | # If true, show URL addresses after external links. | ||||||
| # latex_show_urls = False | #latex_show_urls = False | ||||||
| 
 | 
 | ||||||
| # Documents to append as an appendix to all manuals. | # Documents to append as an appendix to all manuals. | ||||||
| # latex_appendices = [] | #latex_appendices = [] | ||||||
| 
 | 
 | ||||||
| # If false, no module index is generated. | # If false, no module index is generated. | ||||||
| # latex_domain_indices = True | #latex_domain_indices = True | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # -- Options for manual page output ------------------------------------ | # -- Options for manual page output ------------------------------------ | ||||||
|  | @ -245,7 +245,7 @@ man_pages = [ | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| # If true, show URL addresses after external links. | # If true, show URL addresses after external links. | ||||||
| # man_show_urls = False | #man_show_urls = False | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # -- Options for Texinfo output ---------------------------------------- | # -- Options for Texinfo output ---------------------------------------- | ||||||
|  | @ -263,13 +263,13 @@ texinfo_documents = [ | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| # Documents to append as an appendix to all manuals. | # Documents to append as an appendix to all manuals. | ||||||
| # texinfo_appendices = [] | #texinfo_appendices = [] | ||||||
| 
 | 
 | ||||||
| # If false, no module index is generated. | # If false, no module index is generated. | ||||||
| # texinfo_domain_indices = True | #texinfo_domain_indices = True | ||||||
| 
 | 
 | ||||||
| # How to display URL addresses: 'footnote', 'no', or 'inline'. | # How to display URL addresses: 'footnote', 'no', or 'inline'. | ||||||
| # texinfo_show_urls = 'footnote' | #texinfo_show_urls = 'footnote' | ||||||
| 
 | 
 | ||||||
| # If true, do not generate a @detailmenu in the "Top" node's menu. | # If true, do not generate a @detailmenu in the "Top" node's menu. | ||||||
| # texinfo_no_detailmenu = False | #texinfo_no_detailmenu = False | ||||||
|  |  | ||||||
|  | @ -12,30 +12,6 @@ git_lint.git_lint module | ||||||
|     :undoc-members: |     :undoc-members: | ||||||
|     :show-inheritance: |     :show-inheritance: | ||||||
| 
 | 
 | ||||||
| git_lint.option_handler module |  | ||||||
| ------------------------------ |  | ||||||
| 
 |  | ||||||
| .. automodule:: git_lint.option_handler |  | ||||||
|     :members: |  | ||||||
|     :undoc-members: |  | ||||||
|     :show-inheritance: |  | ||||||
| 
 |  | ||||||
| git_lint.options module |  | ||||||
| ----------------------- |  | ||||||
| 
 |  | ||||||
| .. automodule:: git_lint.options |  | ||||||
|     :members: |  | ||||||
|     :undoc-members: |  | ||||||
|     :show-inheritance: |  | ||||||
| 
 |  | ||||||
| git_lint.reporters module |  | ||||||
| ------------------------- |  | ||||||
| 
 |  | ||||||
| .. automodule:: git_lint.reporters |  | ||||||
|     :members: |  | ||||||
|     :undoc-members: |  | ||||||
|     :show-inheritance: |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| Module contents | Module contents | ||||||
| --------------- | --------------- | ||||||
|  |  | ||||||
|  | @ -3,12 +3,8 @@ | ||||||
|    You can adapt this file completely to your liking, but it should at least |    You can adapt this file completely to your liking, but it should at least | ||||||
|    contain the root `toctree` directive. |    contain the root `toctree` directive. | ||||||
| 
 | 
 | ||||||
| Git Lint | Welcome to Git Lint's documentation! | ||||||
| ======== | ====================================== | ||||||
| 
 |  | ||||||
| Git Lint provides a new git command that automatically runs identifiable linters (style |  | ||||||
| and syntax quality assurance programs) against changed files in your current git |  | ||||||
| repository or staging area. |  | ||||||
| 
 | 
 | ||||||
| Contents: | Contents: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ To install Git Lint, run this command in your terminal: | ||||||
| 
 | 
 | ||||||
| .. code-block:: console | .. code-block:: console | ||||||
| 
 | 
 | ||||||
|     $ pip install git-linter |     $ pip install git_lint | ||||||
| 
 | 
 | ||||||
| If you don't have `pip`_ installed, this `Python installation guide`_ can guide | If you don't have `pip`_ installed, this `Python installation guide`_ can guide | ||||||
| you through the process. | you through the process. | ||||||
|  | @ -30,13 +30,13 @@ You can either clone the public repository: | ||||||
| 
 | 
 | ||||||
| .. code-block:: console | .. code-block:: console | ||||||
| 
 | 
 | ||||||
|     $ git clone git://github.com/elfsternberg/git-linter |     $ git clone git://github.com/elfsternberg/git_lint | ||||||
| 
 | 
 | ||||||
| Or download the `tarball`_: | Or download the `tarball`_: | ||||||
| 
 | 
 | ||||||
| .. code-block:: console | .. code-block:: console | ||||||
| 
 | 
 | ||||||
|     $ curl  -OL https://github.com/elfsternberg/git-linter/tarball/master |     $ curl  -OL https://github.com/elfsternberg/git_lint/tarball/master | ||||||
| 
 | 
 | ||||||
| Once you have a copy of the source, you can install it with: | Once you have a copy of the source, you can install it with: | ||||||
| 
 | 
 | ||||||
|  | @ -44,8 +44,10 @@ Once you have a copy of the source, you can install it with: | ||||||
| 
 | 
 | ||||||
|     $ python setup.py install |     $ python setup.py install | ||||||
| 
 | 
 | ||||||
| .. _Github repo: https://github.com/elfsternberg/git-linter | .. _Github repo: https://github.com/elfsternberg/git_lint | ||||||
| .. _tarball: https://github.com/elfsternberg/git-linter/tarball/master | .. _tarball: https://github.com/elfsternberg/git_lint/tarball/master | ||||||
| 
 | 
 | ||||||
| Once installed, please copy the '.git-lint' example file.  You may install this either in | Once installed, you may run the 'git lint --make-config' command, which | ||||||
| your home or repository directory as ``.git-lint``. | 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`` | ||||||
|  |  | ||||||
|  | @ -12,13 +12,24 @@ git lint [options] [filenames] | ||||||
| Options | Options | ||||||
| ------- | ------- | ||||||
| 
 | 
 | ||||||
| .. include:: arguments.rst | .. include: arguments.rst | ||||||
| 
 | 
 | ||||||
| As a pre-commit hook: | As a pre-commit hook: | ||||||
| --------------------- | --------------------- | ||||||
| 
 | 
 | ||||||
| There's a file, pre-commit, in the /bin directory with the project.  (Or you can download | .. code-block:: python | ||||||
| it from the github repository.)  Install it in you .git/hooks/pre-commit file, and | 
 | ||||||
| chmod +x .git/hooks/pre-commit. |     #!/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``: | ||||||
|  | 
 | ||||||
|  | .. code-block:: shell | ||||||
|  | 
 | ||||||
|  |     chmod +x pre-commit | ||||||
|  | 
 | ||||||
|  | Please see the :ref:`api` for more details on options taken by the | ||||||
|  | ``run_precommit()`` and ``run_gitlint`` commands. | ||||||
|      |      | ||||||
| The pre-commit hook is *experimental*.  Please be careful with it. |  | ||||||
|  |  | ||||||
|  | @ -2,6 +2,6 @@ | ||||||
| 
 | 
 | ||||||
| __author__ = 'Kenneth M. "Elf" Sternberg' | __author__ = 'Kenneth M. "Elf" Sternberg' | ||||||
| __email__ = 'elf.sternberg@gmail.com' | __email__ = 'elf.sternberg@gmail.com' | ||||||
| __version__ = '0.0.7' | __version__ = '0.0.4' | ||||||
| 
 | 
 | ||||||
| __all__ = ['git_lint'] | __all__ = ['git_lint'] | ||||||
|  |  | ||||||
|  | @ -5,20 +5,75 @@ from .option_handler import cleanup_options | ||||||
| from .reporters import print_report, print_help, print_linters | from .reporters import print_report, print_help, print_linters | ||||||
| from .git_lint import load_config, run_linters, git_base | from .git_lint import load_config, run_linters, git_base | ||||||
| from getopt import GetoptError | from getopt import GetoptError | ||||||
|  | import os.path | ||||||
| import sys | import sys | ||||||
|  | import time | ||||||
|  | 
 | ||||||
|  | watchdog = False | ||||||
|  | try: | ||||||
|  |     import watchdog | ||||||
|  |     from watchdog.observers import Observer | ||||||
|  |     from watchdog.events import RegexMatchingEventHandler | ||||||
|  | except Exception as e: | ||||||
|  |     pass | ||||||
| 
 | 
 | ||||||
| import gettext | import gettext | ||||||
| _ = gettext.gettext | _ = gettext.gettext | ||||||
| 
 | 
 | ||||||
| NAME = 'git-lint' | NAME = 'git-lint' | ||||||
| VERSION = '0.0.7' | VERSION = '0.0.4' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def remove_unavailable_options(options): | ||||||
|  |     failures = [] + ((watchdog == False and ['monitor']) or []) | ||||||
|  |     return filter(lambda i: i[1] not in failures, options) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def monitor(options, config, filenames): | ||||||
|  | 
 | ||||||
|  |     observer = watchdog.observers.Observer() | ||||||
|  |     skip = ['\.git/'] | ||||||
|  | 
 | ||||||
|  |     def run_monitor_linters(): | ||||||
|  |         (results, | ||||||
|  |          unlintable_filenames, | ||||||
|  |          cant_lint_filenames, | ||||||
|  |          broken_linter_names, | ||||||
|  |          unfindable_filenames) = run_linters(options, config, filenames) | ||||||
|  |          | ||||||
|  |         print_report(results, | ||||||
|  |                      unlintable_filenames, | ||||||
|  |                      cant_lint_filenames, | ||||||
|  |                      broken_linter_names, | ||||||
|  |                      unfindable_filenames, | ||||||
|  |                      options) | ||||||
|  | 
 | ||||||
|  |     class LintMonitor(RegexMatchingEventHandler): | ||||||
|  |         def __init__(self): | ||||||
|  |             super(LintMonitor, self).__init__(ignore_regexes=skip) | ||||||
|  | 
 | ||||||
|  |         def on_created(self, event): | ||||||
|  |             run_monitor_linters() | ||||||
|  | 
 | ||||||
|  |         def on_modified(self, event): | ||||||
|  |             run_monitor_linters() | ||||||
|  | 
 | ||||||
|  |     observer.schedule(LintMonitor(), git_base, recursive=True) | ||||||
|  |     observer.start() | ||||||
|  |     try: | ||||||
|  |         while True: | ||||||
|  |             time.sleep(1) | ||||||
|  |     except KeyboardInterrupt: | ||||||
|  |         observer.stop() | ||||||
|  |     observer.join() | ||||||
| 
 | 
 | ||||||
|              |              | ||||||
| def main(): | def main(): | ||||||
|     if git_base is None: |     if git_base is None: | ||||||
|         sys.exit(_('A git repository was not found.')) |         sys.exit(_('A git repository was not found.')) | ||||||
| 
 | 
 | ||||||
|     (options, filenames, excluded_commands) = cleanup_options(OPTIONS, sys.argv) |     initial_options = remove_unavailable_options(OPTIONS) | ||||||
|  |     (options, filenames, excluded_commands) = cleanup_options(initial_options, sys.argv) | ||||||
| 
 | 
 | ||||||
|     if len(excluded_commands) > 0: |     if len(excluded_commands) > 0: | ||||||
|         print(_('These command line options were ignored due to option precedence.')) |         print(_('These command line options were ignored due to option precedence.')) | ||||||
|  | @ -29,7 +84,7 @@ def main(): | ||||||
|         config = load_config(options, git_base) |         config = load_config(options, git_base) | ||||||
| 
 | 
 | ||||||
|         if 'help' in options: |         if 'help' in options: | ||||||
|             print_help(OPTIONS, NAME) |             print_help(initial_options, NAME) | ||||||
|             return 0 |             return 0 | ||||||
| 
 | 
 | ||||||
|         if 'version' in options: |         if 'version' in options: | ||||||
|  | @ -43,6 +98,9 @@ def main(): | ||||||
|             print_linters(config, broken_linter_names) |             print_linters(config, broken_linter_names) | ||||||
|             return 0 |             return 0 | ||||||
| 
 | 
 | ||||||
|  |         if 'monitor' in options: | ||||||
|  |             return monitor(options, config, filenames) | ||||||
|  | 
 | ||||||
|         (results, |         (results, | ||||||
|          unlintable_filenames, |          unlintable_filenames, | ||||||
|          cant_lint_filenames, |          cant_lint_filenames, | ||||||
|  | @ -62,7 +120,7 @@ def main(): | ||||||
|         return max([i[2] for i in results if len(i)]) |         return max([i[2] for i in results if len(i)]) | ||||||
| 
 | 
 | ||||||
|     except GetoptError as err: |     except GetoptError as err: | ||||||
|         print_help(OPTIONS) |         print_help(initial_options) | ||||||
|         return 1 |         return 1 | ||||||
|      |      | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,18 +9,11 @@ import re | ||||||
| import subprocess | import subprocess | ||||||
| import sys | import sys | ||||||
| import pprint | import pprint | ||||||
| 
 |  | ||||||
| try: | try: | ||||||
|     import configparser |     import configparser | ||||||
| except ImportError as e: | except ImportError as e: | ||||||
|     import ConfigParser as configparser |     import ConfigParser as configparser | ||||||
| 
 | 
 | ||||||
| try:  # noqa: F401 |  | ||||||
|     from typing import Dict, List, Text, Any, Optional, Union, Callable, Tuple  # noqa: F401 |  | ||||||
| except:  # noqa: F401 |  | ||||||
|     pass  # noqa: F401 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| _ = gettext.gettext | _ = gettext.gettext | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -31,20 +24,7 @@ _ = gettext.gettext | ||||||
| #                     |___/ | #                     |___/ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # (commandLineDictionary, repositoryLocation) -> (configurationDictionary | exit) | def find_config_file(options, base): | ||||||
| def load_config(options, base): |  | ||||||
|     """Loads the git-lint configuration file. |  | ||||||
| 
 |  | ||||||
|     Returns the configuration file as a dictionary of dictionaries. |  | ||||||
|     Performs substitutions as specified in the SafeConfigParser |  | ||||||
|     specification; the only one performed currently is the 'repodir' |  | ||||||
|     will be replaced with the base directory of the repository. |  | ||||||
|     Combined with the option to specify the .git-lint configuration as |  | ||||||
|     a directory, this allows users to keep per-project configuration |  | ||||||
|     files for specific linters. |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     def find_config_file(options, base): |  | ||||||
|     """ Returns the configuration file from a prioritized list of locations. |     """ Returns the configuration file from a prioritized list of locations. | ||||||
| 
 | 
 | ||||||
|     Locations are prioritized as: |     Locations are prioritized as: | ||||||
|  | @ -76,6 +56,20 @@ def load_config(options, base): | ||||||
| 
 | 
 | ||||||
|     return matches[0] |     return matches[0] | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | # (commandLineDictionary, repositoryLocation) -> (configurationDictionary | exit) | ||||||
|  | def load_config(options, base): | ||||||
|  |     """Loads the git-lint configuration file. | ||||||
|  | 
 | ||||||
|  |     Returns the configuration file as a dictionary of dictionaries. | ||||||
|  |     Performs substitutions as specified in the SafeConfigParser | ||||||
|  |     specification; the only one performed currently is the 'repodir' | ||||||
|  |     will be replaced with the base directory of the repository. | ||||||
|  |     Combined with the option to specify the .git-lint configuration as | ||||||
|  |     a directory, this allows users to keep per-project configuration | ||||||
|  |     files for specific linters. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|     Linter = namedtuple('Linter', ['name', 'linter']) |     Linter = namedtuple('Linter', ['name', 'linter']) | ||||||
|     path = find_config_file(options, base) |     path = find_config_file(options, base) | ||||||
|     configloader = configparser.SafeConfigParser() |     configloader = configparser.SafeConfigParser() | ||||||
|  | @ -152,6 +146,10 @@ git_head = get_git_head() | ||||||
| #  \___/ \__|_|_|_|\__|_\___/__/ | #  \___/ \__|_|_|_|\__|_\___/__/ | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
|  | def base_file_cleaner(files): | ||||||
|  |     return [file.replace(git_base + '/', '', 1) for file in files] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class MatchFilter: | class MatchFilter: | ||||||
| 
 | 
 | ||||||
|     def __init__(self, config): |     def __init__(self, config): | ||||||
|  | @ -174,34 +172,37 @@ class MatchFilter: | ||||||
| #  \___|_||_\___\__|_\_\ |_|_|_||_\__\___|_| /__/ | #  \___|_||_\___\__|_\_\ |_|_|_||_\__\___|_| /__/ | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
| def linter_exists(linter, label): | def executable_exists(script, label): | ||||||
|     if not len(linter): |     if not len(script): | ||||||
|         sys.exit(_('Syntax error in linter configuration for {} ').format(label)) |         sys.exit( | ||||||
|  |             _('Syntax error in command configuration for {} ').format(label)) | ||||||
| 
 | 
 | ||||||
|     lintername = linter.split(' ').pop(0) |     scriptname = script.split(' ').pop(0) | ||||||
|     if not len(lintername): |     if not len(scriptname): | ||||||
|         sys.exit(_('Syntax error in linter configuration for {} ').format(label)) |         sys.exit( | ||||||
|  |             _('Syntax error in command configuration for {} ').format(label)) | ||||||
| 
 | 
 | ||||||
|     def is_executable(path): |     def is_executable(path): | ||||||
|         return os.path.exists(path) and os.access(path, os.X_OK) |         return os.path.exists(path) and os.access(path, os.X_OK) | ||||||
| 
 | 
 | ||||||
|     if lintername.startswith('/'): |     if scriptname.startswith('/'): | ||||||
|         return (is_executable(lintername) and lintername) or None |         return (is_executable(scriptname) and scriptname) or None | ||||||
| 
 | 
 | ||||||
|     # shutil.which() doesn't appear until Python 3, darnit. |     # shutil.which() doesn't appear until Python 3, darnit. | ||||||
|     possibles = [path for path in |     possibles = [path for path in | ||||||
|                  [os.path.join(path, lintername) |                  [os.path.join(path, scriptname) | ||||||
|                   for path in os.environ.get('PATH').split(':')] |                   for path in os.environ.get('PATH').split(':')] | ||||||
|                  if is_executable(path)] |                  if is_executable(path)] | ||||||
| 
 | 
 | ||||||
|     return (len(possibles) and possibles.pop(0)) or False |     return (len(possibles) and possibles.pop(0)) or False | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_linter_status(config): | def get_working_linter_names(config): | ||||||
|     def get_working_linter_names(config): |  | ||||||
|     return [i.name for i in config |     return [i.name for i in config | ||||||
|                 if linter_exists(i.linter['command'], i.name)] |             if executable_exists(i.linter['command'], i.name)] | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | def get_linter_status(config): | ||||||
|     working_linter_names = get_working_linter_names(config) |     working_linter_names = get_working_linter_names(config) | ||||||
|     broken_linter_names = (set([i.name for i in config]) - set(working_linter_names)) |     broken_linter_names = (set([i.name for i in config]) - set(working_linter_names)) | ||||||
|     return working_linter_names, broken_linter_names |     return working_linter_names, broken_linter_names | ||||||
|  | @ -275,11 +276,6 @@ def get_filelist(options, extras): | ||||||
| 
 | 
 | ||||||
|         return check_for_conflicts(parse_stream([], stream)) |         return check_for_conflicts(parse_stream([], stream)) | ||||||
| 
 | 
 | ||||||
|     def revision_list(): |  | ||||||
|         cmd = ['diff', '--name-only', '-z', options.get('revision')] |  | ||||||
|         return [entry for entry in get_git_response(cmd).split(u'\x00') |  | ||||||
|                 if len(entry) > 0] |  | ||||||
| 
 |  | ||||||
|     def staging_list(): |     def staging_list(): | ||||||
|         """ Return the list of files added or modified to the stage """ |         """ Return the list of files added or modified to the stage """ | ||||||
| 
 | 
 | ||||||
|  | @ -311,9 +307,6 @@ def get_filelist(options, extras): | ||||||
|         working_directory_trans = base_file_filter |         working_directory_trans = base_file_filter | ||||||
| 
 | 
 | ||||||
|     file_list_generator = working_list |     file_list_generator = working_list | ||||||
|     if 'revision' in options: |  | ||||||
|         file_list_generator = revision_list |  | ||||||
|         working_directory_trans = base_file_filter |  | ||||||
|     if 'all' in options: |     if 'all' in options: | ||||||
|         file_list_generator = all_list |         file_list_generator = all_list | ||||||
|     if 'staging' in options: |     if 'staging' in options: | ||||||
|  | @ -329,33 +322,33 @@ def get_filelist(options, extras): | ||||||
| #              |___/       |___/                  |_|  |_| | #              |___/       |___/                  |_|  |_| | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class StagingRunner: | class Runner: | ||||||
|     def __init__(self, filenames): |     def __init__(self, options): | ||||||
|         self.filenames = filenames |         self.runner = ('staging' in options and Runner.staging_wrapper) or Runner.workspace_wrapper | ||||||
| 
 | 
 | ||||||
|     def __enter__(self): |     def __call__(self, run_linters, filenames): | ||||||
|  |         return self.runner(run_linters, filenames) | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def staging_wrapper(run_linters, filenames): | ||||||
|         def time_gather(f): |         def time_gather(f): | ||||||
|             stats = os.stat(f) |             stats = os.stat(f) | ||||||
|             return (f, (stats.st_atime, stats.st_mtime)) |             return (f, (stats.st_atime, stats.st_mtime)) | ||||||
|         self.times = [time_gather(filename) for filename in self.filenames] | 
 | ||||||
|  |         times = [time_gather(file) for file in filenames] | ||||||
|         run_git_command(['stash', '--keep-index']) |         run_git_command(['stash', '--keep-index']) | ||||||
| 
 | 
 | ||||||
|     def __exit__(self, type, value, traceback): |         results = run_linters() | ||||||
|         run_git_command(['reset', '--hard']) |         run_git_command(['reset', '--hard']) | ||||||
|         run_git_command(['stash', 'pop', '--quiet', '--index']) |         run_git_command(['stash', 'pop', '--quiet', '--index']) | ||||||
|         for (filename, timepair) in self.times: | 
 | ||||||
|  |         for (filename, timepair) in times: | ||||||
|             os.utime(filename, timepair) |             os.utime(filename, timepair) | ||||||
|  |         return results | ||||||
| 
 | 
 | ||||||
| 
 |     @staticmethod | ||||||
| class WorkspaceRunner(object): |     def workspace_wrapper(run_linters, filenames): | ||||||
|     def __init__(self, filenames): |         return run_linters() | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
|     def __enter__(self): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
|     def __exit__(self, type, value, traceback): |  | ||||||
|         pass |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #  ___             _ _     _ | #  ___             _ _     _ | ||||||
|  | @ -379,7 +372,7 @@ class Linters: | ||||||
|         """Run one linter against one file. |         """Run one linter against one file. | ||||||
| 
 | 
 | ||||||
|         If the result matches the error condition specified in the configuration file, |         If the result matches the error condition specified in the configuration file, | ||||||
|         return the error code and messages, otherwise return nothing. |         return the error code and messages, either return nothing. | ||||||
|         """ |         """ | ||||||
| 
 | 
 | ||||||
|         cmd = linter['command'] + ' "' + filename + '"' |         cmd = linter['command'] + ' "' + filename + '"' | ||||||
|  | @ -432,9 +425,6 @@ class Linters: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def run_linters(options, config, extras=[]): | def run_linters(options, config, extras=[]): | ||||||
|     if 'pr' in options: |  | ||||||
|         options.pop('pr') |  | ||||||
|         options['revision'] = 'HEAD^..HEAD' |  | ||||||
| 
 | 
 | ||||||
|     def build_config_subset(keys): |     def build_config_subset(keys): | ||||||
|         """ Returns a subset of the configuration, with only those linters mentioned in keys """ |         """ Returns a subset of the configuration, with only those linters mentioned in keys """ | ||||||
|  | @ -444,31 +434,21 @@ def run_linters(options, config, extras=[]): | ||||||
|     all_filenames, unfindable_filenames = get_filelist(options, extras) |     all_filenames, unfindable_filenames = get_filelist(options, extras) | ||||||
| 
 | 
 | ||||||
|     is_lintable = MatchFilter(config) |     is_lintable = MatchFilter(config) | ||||||
|  | 
 | ||||||
|     lintable_filenames = set([filename for filename in all_filenames |     lintable_filenames = set([filename for filename in all_filenames | ||||||
|                               if is_lintable(filename)]) |                               if is_lintable(filename)]) | ||||||
| 
 | 
 | ||||||
|     unlintable_filenames = set(all_filenames) - lintable_filenames |     unlintable_filenames = set(all_filenames) - lintable_filenames | ||||||
| 
 | 
 | ||||||
|     # Filter the linter config down to the selected ones. |  | ||||||
|     if 'only' in options: |  | ||||||
|         config = [linter for linter in config |  | ||||||
|                   if linter.name in options['only']] |  | ||||||
|     elif 'exclude' in options: |  | ||||||
|         config = [linter for linter in config |  | ||||||
|                   if linter.name not in options['exclude']] |  | ||||||
|     if not len(config): |  | ||||||
|         raise RuntimeError('No linters left to run! Be less strict with --only and --exclude.') |  | ||||||
| 
 |  | ||||||
|     working_linter_names, broken_linter_names = get_linter_status(config) |     working_linter_names, broken_linter_names = get_linter_status(config) | ||||||
| 
 | 
 | ||||||
|     cant_lint_filter = MatchFilter(build_config_subset( |     cant_lint_filter = MatchFilter(build_config_subset( | ||||||
|         broken_linter_names)) |         broken_linter_names)) | ||||||
|  | 
 | ||||||
|     cant_lint_filenames = [filename for filename in lintable_filenames |     cant_lint_filenames = [filename for filename in lintable_filenames | ||||||
|                            if cant_lint_filter(filename)] |                            if cant_lint_filter(filename)] | ||||||
| 
 | 
 | ||||||
|     runner = WorkspaceRunner |     runner = Runner(options) | ||||||
|     if 'staging' in options: |  | ||||||
|         runner = StagingRunner |  | ||||||
| 
 | 
 | ||||||
|     linters = Linters(build_config_subset(working_linter_names), |     linters = Linters(build_config_subset(working_linter_names), | ||||||
|                       sorted(lintable_filenames)) |                       sorted(lintable_filenames)) | ||||||
|  | @ -478,8 +458,7 @@ def run_linters(options, config, extras=[]): | ||||||
|         return (dryrun_results, unlintable_filenames, cant_lint_filenames, |         return (dryrun_results, unlintable_filenames, cant_lint_filenames, | ||||||
|                 broken_linter_names, unfindable_filenames) |                 broken_linter_names, unfindable_filenames) | ||||||
| 
 | 
 | ||||||
|     with runner(lintable_filenames): |     results = runner(linters, lintable_filenames) | ||||||
|         results = linters() |  | ||||||
| 
 | 
 | ||||||
|     return (results, unlintable_filenames, cant_lint_filenames, |     return (results, unlintable_filenames, cant_lint_filenames, | ||||||
|             broken_linter_names, unfindable_filenames) |             broken_linter_names, unfindable_filenames) | ||||||
|  |  | ||||||
|  | @ -2,18 +2,8 @@ | ||||||
| # Author: Elf M. Sternberg | # Author: Elf M. Sternberg | ||||||
| 
 | 
 | ||||||
| from functools import reduce | from functools import reduce | ||||||
| from collections import namedtuple |  | ||||||
| import getopt | import getopt | ||||||
| 
 | 
 | ||||||
| try:  # noqa: F401 |  | ||||||
|     from typing import Dict, List, Text, Any, Optional, Union, Callable, Tuple  # noqa: F401 |  | ||||||
| except:  # noqa: F401 |  | ||||||
|     pass  # noqa: F401 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Option = namedtuple('Option', ['short', 'long', 'takes', 'help', 'conflicts'])  # type: str, str, str, str, List[str] |  | ||||||
| Arguments = namedtuple('Arguments', ['arguments', 'filenames', 'excluded'])  # type: Dict[str, str], List[str], List[str] |  | ||||||
| 
 |  | ||||||
| # This was a lot shorter and smarter in Hy... | # This was a lot shorter and smarter in Hy... | ||||||
| 
 | 
 | ||||||
| # A lot of what you see here is separated from git_lint itself, since this will not be | # A lot of what you see here is separated from git_lint itself, since this will not be | ||||||
|  | @ -27,7 +17,6 @@ Arguments = namedtuple('Arguments', ['arguments', 'filenames', 'excluded'])  # t | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def cleanup_options(options, commandline): | def cleanup_options(options, commandline): | ||||||
|     # type: (List[Option], List[str]) -> Arguments |  | ||||||
|     """Takes a table of options and the commandline, and returns a |     """Takes a table of options and the commandline, and returns a | ||||||
|        dictionary of those options that appear on the commandline |        dictionary of those options that appear on the commandline | ||||||
|        along with any extra arguments. |        along with any extra arguments. | ||||||
|  | @ -35,63 +24,52 @@ def cleanup_options(options, commandline): | ||||||
|     :param List(Tuple (string, string, boolean, string, List(string))) options, |     :param List(Tuple (string, string, boolean, string, List(string))) options, | ||||||
|         The table of options: One-letter option, long option, takes arguments, |         The table of options: One-letter option, long option, takes arguments, | ||||||
|         Help text, list of (long) options superseded by this one. |         Help text, list of (long) options superseded by this one. | ||||||
| 
 |  | ||||||
|     : param List(strings) commandline |     : param List(strings) commandline | ||||||
|         The arguments as received by the start-up process |         The arguments as received by the start-up process | ||||||
| 
 |  | ||||||
|     : returns List(strings), List(strings), List(strings) |  | ||||||
|         The longopt dictionary of arguments and associated values (if any) |  | ||||||
|         The list of filenames left after argument processing |  | ||||||
|         The longopt list of arguments that were excluded by argument precedence |  | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     def make_option_streamliner(options): |     def make_option_streamliner(options): | ||||||
|         # type: (List[Option]) -> Callable[[Dict[str, str], Option], Dict[str, str]] |  | ||||||
| 
 | 
 | ||||||
|         """Takes a list of option tuples, and returns a function that takes |         """Takes a list of option tuples, and returns a function that takes | ||||||
|             the output of getopt and reduces it to the longopt key and |             the output of getopt and reduces it to the longopt key and | ||||||
|             associated values as a dictionary. |             associated values as a dictionary. | ||||||
|         """ |         """ | ||||||
| 
 | 
 | ||||||
|         fullset = {}  # type: Dict[str, str] |         fullset = {} | ||||||
|         for option in options: |         for option in options: | ||||||
|             if option.long: |             if option[1]: | ||||||
|                 fullset['--' + option.long] = option.long |                 fullset['--' + option[1]] = option[1] | ||||||
|                 if option.short: |                 if option[0]: | ||||||
|                     fullset['-' + option.short] = option.long |                     fullset['-' + option[0]] = option[1] | ||||||
| 
 | 
 | ||||||
|         def streamliner(acc, it): |         def streamliner(acc, it): | ||||||
|             # type: (Dict[str, str], Option) -> Dict[str, str] |  | ||||||
|             acc[fullset[it[0]]] = it[1] |             acc[fullset[it[0]]] = it[1] | ||||||
|             return acc |             return acc | ||||||
| 
 | 
 | ||||||
|         return streamliner |         return streamliner | ||||||
| 
 | 
 | ||||||
|     def remove_conflicted_options(options, request): |     def remove_conflicted_options(options, request): | ||||||
|         # type: (List[Option], Dict[str, str]) -> Tuple[List[str], List[str]] |  | ||||||
|         """Takes our list of option tuples, and a cleaned copy of what was |         """Takes our list of option tuples, and a cleaned copy of what was | ||||||
|             requested from getopt, and returns a copy of the request |             requested from getopt, and returns a copy of the request | ||||||
|             without any options that are marked as superseded, along with |             without any options that are marked as superseded, along with | ||||||
|             the list of superseded options |             the list of superseded options | ||||||
|         """ |         """ | ||||||
|         def get_excluded_keys(memo, option): |         def get_excluded_keys(memo, opt): | ||||||
|             return memo + option.conflicts |             return memo + ((len(opt) > 4 and opt[4]) or []) | ||||||
| 
 | 
 | ||||||
|         keys = request.keys() |         keys = request.keys() | ||||||
|         marked = [option for option in options if option.long in keys] |         marked = [option for option in options if option[1] in keys] | ||||||
|         exclude = reduce(get_excluded_keys, marked, []) |         exclude = reduce(get_excluded_keys, marked, []) | ||||||
|         excluded = [key for key in keys if key in exclude] |         excluded = [key for key in keys if key in exclude] | ||||||
|         cleaned = {key: request[key] for key in keys |         cleaned = {key: request[key] for key in keys | ||||||
|                    if key not in excluded} |                    if key not in excluded} | ||||||
|         return (cleaned, excluded) |         return (cleaned, excluded) | ||||||
| 
 | 
 | ||||||
|     def shortoptstogo(i): |     def shortoptstogo(i): return i[0] + ((i[2] and ':') or '') | ||||||
|         return i.short + ((i.takes and ':') or '') |  | ||||||
| 
 | 
 | ||||||
|     def longoptstogo(i): |     def longoptstogo(i): return i[1] + ((i[2] and '=') or '') | ||||||
|         return i.long + ((i.takes and '=') or '') |  | ||||||
| 
 | 
 | ||||||
|     optstringsshort = ''.join([shortoptstogo(opt) for opt in options if opt.short]) |     optstringsshort = ''.join([shortoptstogo(opt) for opt in options]) | ||||||
|     optstringslong = [longoptstogo(opt) for opt in options] |     optstringslong = [longoptstogo(opt) for opt in options] | ||||||
|     (chosen_options, filenames) = getopt.getopt(commandline[1:], |     (chosen_options, filenames) = getopt.getopt(commandline[1:], | ||||||
|                                          optstringsshort, |                                          optstringsshort, | ||||||
|  | @ -104,4 +82,4 @@ def cleanup_options(options, commandline): | ||||||
|     (ret, excluded) = remove_conflicted_options( |     (ret, excluded) = remove_conflicted_options( | ||||||
|         options, reduce(streamline_options, chosen_options, {})) |         options, reduce(streamline_options, chosen_options, {})) | ||||||
| 
 | 
 | ||||||
|     return Arguments(ret, filenames, excluded) |     return (ret, filenames, excluded) | ||||||
|  |  | ||||||
|  | @ -1,45 +1,40 @@ | ||||||
| import gettext | import gettext | ||||||
| from option_handler import Option |  | ||||||
| 
 |  | ||||||
| _ = gettext.gettext | _ = gettext.gettext | ||||||
| 
 | 
 | ||||||
| OPTIONS = [ | OPTIONS = [ | ||||||
|     Option('o', 'only', True, |     ('o', 'only', True, | ||||||
|      _('A comma-separated list of only those linters to run'), ['exclude']), |      _('A comma-separated list of only those linters to run'), ['exclude']), | ||||||
|     Option('x', 'exclude', True, |     ('x', 'exclude', True, | ||||||
|      _('A comma-separated list of linters to skip'), []), |      _('A comma-separated list of linters to skip'), []), | ||||||
|     Option('l', 'linters', False, |     ('l', 'linters', False, | ||||||
|      _('Show the list of configured linters'), []), |      _('Show the list of configured linters'), []), | ||||||
|     Option('b', 'base', False, |     ('b', 'base', False, | ||||||
|      _('Check all changed files in the repository, not just those in the current directory.'), []), |      _('Check all changed files in the repository, not just those in the current directory.'), []), | ||||||
|     Option('a', 'all', False, |     ('a', 'all', False, | ||||||
|            _('Scan all files in the repository, not just those that have changed.'), ['revision']), |      _('Scan all files in the repository, not just those that have changed.'), []), | ||||||
|     Option('r', 'revision', True, |     ('e', 'every', False, | ||||||
|            _('Scan all files changed between revisions'), []), |  | ||||||
|     Option(None, 'pr', False, |  | ||||||
|            _('Scan all files changed between head and previous check-in'), ['revision']), |  | ||||||
|     Option('e', 'every', False, |  | ||||||
|      _('Short for -b -a: scan everything'), []), |      _('Short for -b -a: scan everything'), []), | ||||||
|     Option('w', 'workspace', False, |     ('w', 'workspace', False, | ||||||
|      _('Scan the workspace'), ['staging']), |      _('Scan the workspace'), ['staging']), | ||||||
|     Option('s', 'staging', False, |     ('s', 'staging', False, | ||||||
|            _('Scan the staging area (useful for pre-commit).'), []), |      _('Scan the staging area (useful for pre-commit).'), ['monitor']), | ||||||
|     #    ('g', 'changes', False, |     ('g', 'changes', False, | ||||||
|     #     _("Report lint failures only for diff'd sections"), ['complete']), |      _("Report lint failures only for diff'd sections"), ['complete']), | ||||||
|     #    ('p', 'complete', False, |     ('p', 'complete', False, | ||||||
|     #     _('Report lint failures for all files'), []), |      _('Report lint failures for all files'), []), | ||||||
|     Option('t', 'bylinter', False, |     ('t', 'bylinter', False, | ||||||
|      _('Group the reports by linter first as they appear in the config file [default]'), []), |      _('Group the reports by linter first as they appear in the config file [default]'), []), | ||||||
|     Option('f', 'byfile', False, |     ('f', 'byfile', False, | ||||||
|      _('Group the reports by file first'), []), |      _('Group the reports by file first'), []), | ||||||
|     Option('d', 'dryrun', False, |     ('d', 'dryrun', False, | ||||||
|      _('Dry run - report what would be done, but do not run linters'), []), |      _('Dry run - report what would be done, but do not run linters'), []), | ||||||
|     Option('c', 'config', True, |     ('m', 'monitor', False, | ||||||
|  |      _('Run continuously, monitoring filesytem for changes'), []), | ||||||
|  |     ('c', 'config', True, | ||||||
|      _('Path to config file'), []), |      _('Path to config file'), []), | ||||||
|     Option('h', 'help', False, |     ('h', 'help', False, | ||||||
|      _('This help message'), []), |      _('This help message'), []), | ||||||
|     Option('V', 'verbose', False, |     ('v', 'version', False, | ||||||
|            _('A slightly more verbose output'), []), |  | ||||||
|     Option('v', 'version', False, |  | ||||||
|      _('Version information'), []) |      _('Version information'), []) | ||||||
| ] | ] | ||||||
|  |   | ||||||
|  |  | ||||||
|  | @ -1,19 +1,10 @@ | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
| from functools import reduce |  | ||||||
| from .git_lint import load_config, run_linters, git_base |  | ||||||
| import operator |  | ||||||
| import gettext | import gettext | ||||||
| _ = gettext.gettext | _ = gettext.gettext | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def print_report(results, unlintable_filenames, cant_lint_filenames, | # ICK.  Mutation, references, and hidden assignment. | ||||||
|                  broken_linter_names, unfindable_filenames, options={'bylinter': True}): | def group_by(iterable, field_id): | ||||||
| 
 |  | ||||||
|     def base_file_cleaner(files): |  | ||||||
|         return [file.replace(git_base + '/', '', 1) for file in files] |  | ||||||
| 
 |  | ||||||
|     # ICK.  Mutation, references, and hidden assignment. |  | ||||||
|     def group_by(iterable, field_id): |  | ||||||
|     results = [] |     results = [] | ||||||
|     keys = {} |     keys = {} | ||||||
|     for obj in iterable: |     for obj in iterable: | ||||||
|  | @ -25,46 +16,37 @@ def print_report(results, unlintable_filenames, cant_lint_filenames, | ||||||
|         results.append((key, keys[key])) |         results.append((key, keys[key])) | ||||||
|     return results |     return results | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | def print_report(results, unlintable_filenames, cant_lint_filenames, | ||||||
|  |                  broken_linter_names, unfindable_filenames, options={'bylinter': True}): | ||||||
|     sort_position = 1 |     sort_position = 1 | ||||||
|     grouping = _('Linter: {}') |     grouping = _('Linter: {}') | ||||||
|     if 'byfile' in options: |     if 'byfile' in options: | ||||||
|         sort_position = 0 |         sort_position = 0 | ||||||
|         grouping = _('Filename: {}') |         grouping = _('Filename: {}') | ||||||
|     grouped_results = group_by(results, sort_position) |     grouped_results = group_by(results, sort_position) | ||||||
| 
 |  | ||||||
|     for group in grouped_results: |     for group in grouped_results: | ||||||
|         messages = reduce(operator.add, [item[3] for item in group[1]], []) |  | ||||||
|         if len(messages) == 0: |  | ||||||
|             continue |  | ||||||
|         print(grouping.format(group[0])) |         print(grouping.format(group[0])) | ||||||
|         for (filename, lintername, returncode, text) in group[1]: |         for (filename, lintername, returncode, text) in group[1]: | ||||||
|             if text: |             print('\n'.join(text)) | ||||||
|                 print('\n'.join(base_file_cleaner(text))) |  | ||||||
|         print('') |         print('') | ||||||
|         print ('') |     if len(broken_linter_names): | ||||||
| 
 |         print(_('These linters could not be run:'), ','.join(broken_linter_names)) | ||||||
|     if len(broken_linter_names) and (len(cant_lint_filenames) or ('verbose' in options)): |  | ||||||
|         print(_('Linters not found:'), ','.join(broken_linter_names)) |  | ||||||
|         if len(cant_lint_filenames): |         if len(cant_lint_filenames): | ||||||
|             print('  ' + _('Files not linted:')) |             print(_('As a result, these files were not linted:')) | ||||||
|             print('\n'.join(['    {}'.format(f) for f in cant_lint_filenames])) |             print('\n'.join(['    {}'.format(f) for f in cant_lint_filenames])) | ||||||
|         print('') |     if len(unlintable_filenames): | ||||||
| 
 |         print(_('The following files had no recognizeable linters:')) | ||||||
|     if len(unlintable_filenames) and ('verbose' in options): |  | ||||||
|         print(_('No recognizeable linters for:')) |  | ||||||
|         print('\n'.join(['    {}'.format(f) for f in unlintable_filenames])) |         print('\n'.join(['    {}'.format(f) for f in unlintable_filenames])) | ||||||
|         print('') |  | ||||||
| 
 |  | ||||||
|     if len(unfindable_filenames): |     if len(unfindable_filenames): | ||||||
|         print(_('Files not found:')) |         print(_('The following files could not be found:')) | ||||||
|         print('\n'.join(['    {}'.format(f) for f in unfindable_filenames])) |         print('\n'.join(['    {}'.format(f) for f in unfindable_filenames])) | ||||||
|         print('') |  | ||||||
| 
 | 
 | ||||||
|          |          | ||||||
| def print_help(options, name): | def print_help(options, name): | ||||||
|     print(_('Usage: {} [options] [filenames]').format(name)) |     print(_('Usage: {} [options] [filenames]').format(name)) | ||||||
|     for item in options: |     for item in options: | ||||||
|         print(' {:<2}  --{:<12}  {}'.format((item[0] and ('-' + item[0])) or '', item[1], item[3])) |         print(' -{:<1}  --{:<12}  {}'.format(item[0], item[1], item[3])) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def print_version(name, version): | def print_version(name, version): | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| [bumpversion] | [bumpversion] | ||||||
| current_version = 0.0.7 | current_version = 0.0.4 | ||||||
| commit = True | commit = True | ||||||
| tag = True | tag = True | ||||||
| 
 | 
 | ||||||
|  | @ -16,4 +16,3 @@ universal = 1 | ||||||
| 
 | 
 | ||||||
| [flake8] | [flake8] | ||||||
| exclude = docs | exclude = docs | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								setup.py
								
								
								
								
							
							
						
						
									
										21
									
								
								setup.py
								
								
								
								
							|  | @ -1,22 +1,7 @@ | ||||||
| #!/usr/bin/env python | #!/usr/bin/env python | ||||||
| import re | # -*- coding: utf-8 -*- | ||||||
| import sys |  | ||||||
| import argparse |  | ||||||
| import os.path |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_data_files(prefix): |  | ||||||
|     if prefix.startswith('/System/Library/Frameworks'): |  | ||||||
|         return [] |  | ||||||
|     return [(os.path.join(prefix, 'share/man/man1'), ['docs/_build/man/git-lint.1'])] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| parser = argparse.ArgumentParser() |  | ||||||
| parser.add_argument('--prefix', default='', |  | ||||||
|                     help='prefix to install data files') |  | ||||||
| opts, _ = parser.parse_known_args(sys.argv) |  | ||||||
| prefix = opts.prefix or sys.prefix or '/usr' |  | ||||||
| 
 |  | ||||||
| try: | try: | ||||||
|     from setuptools import setup |     from setuptools import setup | ||||||
| except ImportError: | except ImportError: | ||||||
|  | @ -39,7 +24,7 @@ test_requirements = [ | ||||||
| 
 | 
 | ||||||
| setup( | setup( | ||||||
|     name='git_linter', |     name='git_linter', | ||||||
|     version='0.0.7', |     version='0.0.4', | ||||||
|     description="A git command to lint everything in your workspace (or stage) that was changed since the last commit.", |     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, |     long_description=readme + '\n\n' + history, | ||||||
|     author='Kenneth M. "Elf" Sternberg', |     author='Kenneth M. "Elf" Sternberg', | ||||||
|  | @ -51,11 +36,9 @@ setup( | ||||||
|     package_dir={'git_lint': |     package_dir={'git_lint': | ||||||
|                  'git_lint'}, |                  'git_lint'}, | ||||||
|     include_package_data=True, |     include_package_data=True, | ||||||
|     data_files=get_data_files(prefix), |  | ||||||
|     install_requires=requirements, |     install_requires=requirements, | ||||||
|     license="MIT", |     license="MIT", | ||||||
|     zip_safe=False, |     zip_safe=False, | ||||||
|     scripts=['bin/git-lint-style'], |  | ||||||
|     keywords='git lint style syntaxt development', |     keywords='git lint style syntaxt development', | ||||||
|     entry_points={ |     entry_points={ | ||||||
|         'console_scripts': [ |         'console_scripts': [ | ||||||
|  |  | ||||||
|  | @ -102,17 +102,6 @@ def test_02_empty_repository(): | ||||||
|         assert stderr.startswith('No configuration file found,') |         assert stderr.startswith('No configuration file found,') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # It should behave well when the repository is empty and we're |  | ||||||
| # running against staging. |  | ||||||
|          |  | ||||||
| def test_02b_empty_repository(): |  | ||||||
|     with gittemp() as path: |  | ||||||
|         os.chdir(path) |  | ||||||
|         shell('git init') |  | ||||||
|         (stdout, stderr, rc) = fullshell('git lint -s') |  | ||||||
|         assert stderr.startswith('No configuration file found,') |  | ||||||
|          |  | ||||||
| 
 |  | ||||||
| def test_03_simple_repository(): | def test_03_simple_repository(): | ||||||
|     with gittemp() as path: |     with gittemp() as path: | ||||||
|         os.chdir(path) |         os.chdir(path) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | #!/usr/bin/hy   ; -*- mode: clojure -*- | ||||||
|  | (import subprocess os sys os.path) | ||||||
|  | 
 | ||||||
|  | (defn fmit [formatstring iterable] | ||||||
|  |   (apply .format (+ [formatstring] (list iterable)))) | ||||||
|  | 
 | ||||||
|  | (defmain [&rest args] | ||||||
|  |   (let [[git_dir (subprocess.check_output ["git" "rev-parse" "--show-toplevel"])]] | ||||||
|  |     (.append sys.path (os.path.join git_dir "git_lint")) | ||||||
|  |     (import [git_lint [git_lint]]) | ||||||
|  |     (print (.join "\n" (map (fn [i] (if (get i 2) | ||||||
|  |                                       (+ (fmit "\item[\oOptArg{{-{0}}}{{ names}} " i) | ||||||
|  |                                          (fmit "\oOptArg{{--{1}}}={{ names}}] " i) | ||||||
|  |                                          (fmit "{3}" i)) | ||||||
|  |                                       (+ (fmit "\item[\oOptArg{{-{0}}} " i) | ||||||
|  |                                          (fmit "\oOptArg{{--{1}}}] " i) | ||||||
|  |                                          (fmit "{3}" i)))) | ||||||
|  |                             git_lint.OPTIONS_LIST))))) | ||||||
|  |                  | ||||||
|  |      | ||||||
		Loading…
	
		Reference in New Issue