├── .editorconfig ├── .flake8 ├── .gitignore ├── HISTORY.rst ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.rst ├── build_pex.sh ├── ctm ├── ctm.py ├── requirements-dev.txt ├── requirements-pex.txt ├── requirements.txt └── setup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [*.py] 12 | indent_style = space 13 | indent_size = 4 14 | 15 | # isort 16 | lines_after_imports = 2 17 | not_skip=__init__.py 18 | 19 | [Makefile] 20 | indent_style = tab 21 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | exclude = 3 | .eggs, 4 | .git, 5 | .tox, 6 | .cache, 7 | __pycache__, 8 | dist, 9 | build 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | .static_storage/ 56 | .media/ 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | Release History 2 | =============== 3 | 4 | 0.2.0 / 2018-02-09 5 | ------------------ 6 | 7 | * Fancy version output 8 | 9 | 10 | 0.1.0 / 2018-02-08 11 | ------------------ 12 | 13 | * First version 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Pavlo Dmytrenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst HISTORY.rst LICENSE 2 | include requirements.txt 3 | include requirements-dev.txt 4 | include requirements-pex.txt 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OK_COLOR=\033[32;01m 2 | NO_COLOR=\033[0m 3 | 4 | .PHONY: build 5 | 6 | name=ctm.py 7 | 8 | flake: 9 | @echo "$(OK_COLOR)==> Linting code ...$(NO_COLOR)" 10 | @flake8 . 11 | 12 | lint: 13 | @echo "$(OK_COLOR)==> Linting code ...$(NO_COLOR)" 14 | @pylint setup.py $(name) -rn -f colorized 15 | 16 | isort-all: 17 | isort -rc --atomic --verbose setup.py $(name) 18 | 19 | install-dev: 20 | @pip install -r requirements.txt 21 | @pip install -r requirements-dev.txt 22 | 23 | clean-pyc: 24 | @echo "$(OK_COLOR)==> Cleaning bytecode ...$(NO_COLOR)" 25 | @find . -type d -name '__pycache__' -exec rm -rf {} + 26 | @find . -name '*.pyc' -exec rm -f {} + 27 | @find . -name '*.pyo' -exec rm -f {} + 28 | @find . -name '*~' -exec rm -f {} + 29 | 30 | rm-build: 31 | @rm -rf build dist .egg $(name).egg-info 32 | 33 | # requires docutils and pygments to be installed 34 | # -s stands for strict (raises errors instead of warnings) 35 | check-rst: 36 | @python setup.py check --restructuredtext -s 37 | 38 | build: rm-build 39 | @echo "$(OK_COLOR)==> Building sdist and bdist_wheel $(NO_COLOR)" 40 | @python setup.py sdist 41 | @python setup.py bdist_wheel --universal 42 | 43 | build-pex: rm-build build 44 | @echo "$(OK_COLOR)==> Building PEX $(NO_COLOR)" 45 | @./build_pex.sh 46 | 47 | 48 | publish: flake check-rst rm-build 49 | @echo "$(OK_COLOR)==> Publishing...$(NO_COLOR)" 50 | @python setup.py sdist upload -r pypi 51 | @python setup.py bdist_wheel --universal upload -r pypi 52 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | git-ctm |pypi| |Wheel| |Versions| |License| 2 | =========================================== 3 | 4 | git-ctm = ``git commit`` Time Machine 5 | 6 | Sometimes you need to create a commit with particular timestamp. 7 | **git-ctm** provides a command-line tool ``ctm`` for easy committing with desired timestamp: 8 | 9 | 10 | .. code:: bash 11 | 12 | $ ctm -d 'Thu Feb 8 03:14:15 2018 +0200' -m 'my commit message' 13 | 14 | # is the same as 15 | $ GIT_AUTHOR_DATE='Thu Feb 8 03:14:15 2018 +0200' \ 16 | GIT_COMMITTER_DATE='Thu Feb 8 03:14:15 2018 +0200' \ 17 | git commit -m 'my commit message' 18 | 19 | *All commits in this project are done with* ``ctm`` *itself.* 20 | 21 | 22 | Installation 23 | ------------ 24 | 25 | From `PyPI`_ using ``pip`` package manager: 26 | 27 | .. code:: bash 28 | 29 | pip install --upgrade git-ctm 30 | 31 | 32 | Or install the latest sources from GitHub: 33 | 34 | .. code:: bash 35 | 36 | pip install https://github.com/pavdmyt/git-ctm/archive/master.zip 37 | 38 | 39 | Or just put ``ctm`` `PEX`_ (Python EXecutable) file somewhere in the ``$PATH``: 40 | 41 | .. code:: bash 42 | 43 | $ git clone https://github.com/pavdmyt/git-ctm.git 44 | $ cd git-ctm 45 | $ sudo cp ctm /usr/local/bin/ 46 | 47 | Now ``ctm`` command-line tool should be available to use, try: 48 | 49 | .. code:: bash 50 | 51 | ctm --version 52 | 53 | 54 | Usage 55 | ----- 56 | 57 | .. code:: bash 58 | 59 | $ ctm --help 60 | Usage: ctm -d -m 61 | ctm -p 62 | 63 | -d Commit date and time 64 | -m Commit message 65 | -p Print date template 66 | 67 | --help Print usage 68 | --version Print version 69 | 70 | 71 | Development 72 | ----------- 73 | 74 | Clone the repository: 75 | 76 | .. code:: bash 77 | 78 | git clone https://github.com/pavdmyt/git-ctm.git 79 | 80 | 81 | Install dependencies: 82 | 83 | .. code:: bash 84 | 85 | make install-dev 86 | 87 | 88 | Lint code: 89 | 90 | .. code:: bash 91 | 92 | make lint 93 | 94 | 95 | Contributing 96 | ------------ 97 | 98 | 1. Fork it! 99 | 2. Create your feature branch: ``git checkout -b my-new-feature`` 100 | 3. Commit your changes: ``git commit -m 'Add some feature'`` 101 | 4. Push to the branch: ``git push origin my-new-feature`` 102 | 5. Submit a pull request 103 | 6. Make sure tests are passing 104 | 105 | 106 | License 107 | ------- 108 | 109 | MIT - Pavlo Dmytrenko 110 | 111 | 112 | .. |pypi| image:: https://img.shields.io/pypi/v/git-ctm.svg 113 | :target: https://pypi.org/project/git-ctm/ 114 | .. |Versions| image:: https://img.shields.io/pypi/pyversions/git-ctm.svg 115 | :target: https://pypi.org/project/git-ctm/ 116 | .. |Wheel| image:: https://img.shields.io/pypi/wheel/git-ctm.svg 117 | :target: https://pypi.org/project/git-ctm/ 118 | .. |License| image:: https://img.shields.io/pypi/l/git-ctm.svg 119 | :target: https://pypi.org/project/git-ctm/ 120 | 121 | 122 | .. _PyPI: https://pypi.org/ 123 | .. _PEX: https://github.com/pantsbuild/pex 124 | -------------------------------------------------------------------------------- /build_pex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shebang="/usr/bin/env python" 4 | 5 | # -r : recreate virtualenv 6 | # -o : output file 7 | # -c : console_script entry point 8 | # -v : verbose 9 | # 10 | # -f PATH/URL, --find-links=PATH/URL, --repo=PATH/URL 11 | # Additional repository path (directory or URL) to look 12 | # for requirements. 13 | # --python-shebang=PYTHON_SHEBANG 14 | # The exact shebang (#!...) line to add at the top of 15 | # the PEX file minus the #!. This overrides the default 16 | # behavior, which picks an environment python 17 | # interpreter compatible with the one used to build the 18 | # PEX file. 19 | # 20 | # More about interpreter and shebang options: 21 | # https://github.com/pantsbuild/pex/issues/4 22 | # https://github.com/pantsbuild/pex/issues/53 23 | # 24 | PEX_VERBOSE=5 \ 25 | pex \ 26 | -r requirements-pex.txt \ 27 | -f dist \ 28 | -o "ctm" \ 29 | -c ctm \ 30 | --python-shebang="$shebang" \ 31 | -v 32 | -------------------------------------------------------------------------------- /ctm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavdmyt/git-ctm/3f6592422f838c41fbc870eeadb7045578045953/ctm -------------------------------------------------------------------------------- /ctm.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | git Commit Time Machine 5 | ~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | A command-line tool for easy commits with desired timestamp. 8 | 9 | :copyright: (c) 2018 by Pavlo Dmytrenko. 10 | :license: MIT, see LICENSE for more details. 11 | """ 12 | 13 | from __future__ import print_function 14 | 15 | import os 16 | 17 | from docopt import docopt 18 | 19 | 20 | __version__ = '0.2.0' 21 | 22 | 23 | CLI_SPEC = """\ 24 | Usage: ctm -d -m 25 | ctm -p 26 | 27 | -d Commit date and time 28 | -m Commit message 29 | -p Print date template 30 | 31 | --help Print usage 32 | --version Print version 33 | 34 | """ 35 | 36 | 37 | CMD_TMPL = ("GIT_AUTHOR_DATE='{date}' " 38 | "GIT_COMMITTER_DATE='{date}' " 39 | "git commit -m '{msg}'") 40 | 41 | 42 | DATE_TMPL = 'Wed Feb 7 11:11:11 2018 +0200' 43 | 44 | 45 | VERSION_TMPL = """\ 46 | 47 | ██████╗████████╗███╗ ███╗ 48 | ██╔════╝╚══██╔══╝████╗ ████║ 49 | ██║ ██║ ██╔████╔██║ 50 | ██║ ██║ ██║╚██╔╝██║ 51 | ╚██████╗ ██║ ██║ ╚═╝ ██║ 52 | ╚═════╝ ╚═╝ ╚═╝ ╚═╝ 53 | 54 | git Commit Time Machine 55 | https://github.com/pavdmyt/git-ctm 56 | 57 | VERSION %s 58 | """ 59 | 60 | 61 | def main(): 62 | args = docopt(CLI_SPEC, version=VERSION_TMPL % __version__) 63 | date = args['-d'] 64 | msg = args['-m'] 65 | print_tmpl = args['-p'] 66 | 67 | if print_tmpl: 68 | print(repr(DATE_TMPL)) 69 | return 70 | 71 | cmd = CMD_TMPL.format(**{'date': date, 'msg': msg}) 72 | print(cmd) 73 | os.system(cmd) 74 | 75 | 76 | if __name__ == '__main__': 77 | main() 78 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | flake8 2 | isort 3 | pylint 4 | pex 5 | 6 | # required for `python setup.py check --restructuredtext -s` 7 | docutils 8 | pygments 9 | -------------------------------------------------------------------------------- /requirements-pex.txt: -------------------------------------------------------------------------------- 1 | docopt 2 | git-ctm 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | docopt 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import codecs 5 | import os 6 | 7 | from setuptools import setup 8 | 9 | 10 | try: 11 | # Python 3 12 | from os import dirname 13 | except ImportError: 14 | # Python 2 15 | from os.path import dirname 16 | 17 | 18 | here = os.path.abspath(dirname(__file__)) 19 | 20 | 21 | def read_version(module_name): 22 | with open(module_name, 'r') as fd: 23 | for line in fd: 24 | if line.startswith('__version__ = '): 25 | return line.split()[-1].strip().strip("'") 26 | 27 | 28 | with codecs.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: 29 | long_description = '\n' + f.read() 30 | 31 | 32 | required = [ 33 | 'docopt', 34 | ] 35 | 36 | 37 | setup( 38 | name='git-ctm', 39 | version=read_version('ctm.py'), 40 | author='Pavlo Dmytrenko', 41 | author_email='mail@pavdmyt.com', 42 | license='MIT', 43 | description='Git commit time machine.', 44 | long_description=long_description, 45 | url='https://github.com/pavdmyt/git-ctm', 46 | download_url='https://github.com/pavdmyt/git-ctm/archive/master.zip', 47 | py_modules=['ctm'], 48 | install_requires=required, 49 | entry_points={ 50 | 'console_scripts': [ 51 | 'ctm = ctm:main', 52 | ] 53 | }, 54 | platforms=['any'], 55 | classifiers=[ 56 | 'Development Status :: 3 - Alpha', 57 | 'Environment :: Console', 58 | 'Intended Audience :: Developers', 59 | 'Intended Audience :: System Administrators', 60 | 'License :: OSI Approved :: MIT License', 61 | 'Natural Language :: English', 62 | 'Operating System :: OS Independent', 63 | 'Programming Language :: Python', 64 | 'Programming Language :: Python :: 2', 65 | 'Programming Language :: Python :: 2.7', 66 | 'Programming Language :: Python :: 3', 67 | 'Programming Language :: Python :: 3.3', 68 | 'Programming Language :: Python :: 3.4', 69 | 'Programming Language :: Python :: 3.5', 70 | 'Programming Language :: Python :: 3.6', 71 | 'Programming Language :: Python :: Implementation :: CPython', 72 | 'Programming Language :: Python :: Implementation :: PyPy', 73 | 'Topic :: Software Development', 74 | 'Topic :: Software Development :: Version Control', 75 | 'Topic :: Software Development :: Version Control :: Git', 76 | 'Topic :: Utilities', 77 | ] 78 | ) 79 | --------------------------------------------------------------------------------