diff --git a/docs/changelog.md b/docs/changelog.md index f8d4eee..aeae86e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -170,3 +170,21 @@ ## [0.1.5] - 2021-01-07 +## [Unreleased] + +**Bugfix** + +- No template available + - Print a message when the lenght template list is 0 + +**Enhancement** + +- Local install template + - Add a local installation of templates + - Add an update option to upgrade local templates from local source + +**Structure** + +- Distinct workflow and setup cmd + - Moves file to workflow or setup directories + diff --git a/git_improved/configurations.py b/git_improved/configurations.py deleted file mode 100644 index ae4d8db..0000000 --- a/git_improved/configurations.py +++ /dev/null @@ -1,39 +0,0 @@ -ACTION_PUBLISH_RELEASE_ON_TAG = """ -name: Publish release - -on: - push: - tags: - - "*" - -jobs: - create-release: - name: Create Release - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Get the version - id: get_version - run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/} - - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - body_path: docs/releases/${{ steps.get_version.outputs.VERSION }}.md - draft: false - prerelease: false -""" - -BUMPVERSION_CONFIG = """ -[bumpversion] -current_version = 0.0.1 - -# [bumpversion:file:setup.py] -""" \ No newline at end of file diff --git a/git_improved/commands/__init__.py b/git_improved/setup/__init__.py similarity index 100% rename from git_improved/commands/__init__.py rename to git_improved/setup/__init__.py diff --git a/git_improved/setup/commands/__init__.py b/git_improved/setup/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/git_improved/commands/setup.py b/git_improved/setup/commands/setup.py similarity index 51% rename from git_improved/commands/setup.py rename to git_improved/setup/commands/setup.py index bb51d1d..3817d02 100644 --- a/git_improved/commands/setup.py +++ b/git_improved/setup/commands/setup.py @@ -2,9 +2,8 @@ import shutil import argparse import subprocess -from ..templates import TEMPLATES -from ..command import Command -from ..changelog import Changelog +from ...command import Command +from ...changelog import Changelog from ..template import setup_project @@ -50,4 +49,38 @@ def parser(): return parser def run(*, directory=".", template=None, verbose=False): - setup_project(template=template, destination=directory) + + releases_directory='docs/releases' + changelog_path='docs/changelog.md' + no_github_action=False + + # create releases_directory and add a .gitkeep to ensure it wont be empty + release_gitkeep_path = os.path.join(releases_directory, '.gitkeep') + try: + open(release_gitkeep_path) + print('[Warning] GitHub action already exists. Make sure it contains configuration to document changes on release.') + except FileNotFoundError: + os.makedirs(releases_directory, exist_ok=True) + with open(release_gitkeep_path, 'w') as gitkeep: + pass + print('Releases directory created in:', releases_directory) + + # create changelog if it doesn't exists + try: + changelog = Changelog.parse(changelog_path) + except FileNotFoundError: + directory = os.path.dirname(os.path.abspath(changelog_path)) + os.makedirs(directory, exist_ok=True) + changelog = Changelog.parse(changelog_path) + + + if not is_git_initialized(): + subprocess.call(['git', 'init'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + subprocess.call(['git', 'branch -m master main'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + print('Git repository initialized...') + + commit_configuration() + + # setup templates + if template is not None: + setup_project(template=template, destination=directory) diff --git a/git_improved/commands/template.py b/git_improved/setup/commands/template.py similarity index 72% rename from git_improved/commands/template.py rename to git_improved/setup/commands/template.py index 40d24f9..1d3704b 100644 --- a/git_improved/commands/template.py +++ b/git_improved/setup/commands/template.py @@ -1,9 +1,9 @@ import argparse -from ..exceptions import ValidationError -from ..command import Command -from ..template import Template, GitCredentials -from ..shell import display_table +from ...exceptions import ValidationError +from ...command import Command +from ...template import Template, GitCredentials +from ...shell import display_table class TemplateCommand(metaclass=Command): @@ -18,6 +18,11 @@ def parser(): install_parser.add_argument("--user", help="username used to autenticate if required") install_parser.add_argument("--token", help="pass a token or password to authenticate if required") + local_install_parser = subparsers.add_parser("local", help="install a template from a local source") + local_install_parser.add_argument("alias", help="the name you want to use locally to reference this template") + local_install_parser.add_argument("source", help="local path where target template is located") + local_install_parser.add_argument("-u", "--upgrade", action="store_true", help="update the given template") + update_parser = subparsers.add_parser("update", help="update given templates (default to all).") update_parser.add_argument("templates", nargs="*", help="if you pass a list of templates, only these templates will be updated...") update_parser.add_argument("-v", "--verbose", action="store_true", help="(verbose) display additional informations...") @@ -34,20 +39,25 @@ def validate(args): if not args.command: raise ValidationError('You must specify a command') - def run(*, command, alias=None, search=None, branch=None, user=None, token=None, origin=None, templates=None, verbose=False): + def run(*, command, alias=None, search=None, branch=None, user=None, token=None, origin=None, source=None, upgrade=None, templates=None, verbose=False): git_template = Template() if command == "install": # ensure that user can read this repository (=> public repo or proper authentication) GitCredentials().require_credentials(repository=origin) git_template.install(template=alias, origin=origin, branch=branch) + elif command == "local": + git_template.local_install(template=alias, source=source, upgrade=upgrade) elif command == "update": templates = templates if templates else git_template.search() for template in templates: git_template.update(template, verbose=verbose) elif command == "list": templates = git_template.search(query=search) - display_table(templates) + if len(templates) == 0: + print("no templates available") + else: + display_table(templates) elif command == "rm": for template in templates: git_template.remove(template) diff --git a/git_improved/template.py b/git_improved/setup/template.py similarity index 89% rename from git_improved/template.py rename to git_improved/setup/template.py index 05907a5..2877c94 100644 --- a/git_improved/template.py +++ b/git_improved/setup/template.py @@ -1,15 +1,15 @@ import os import re import json -import shutil import requests import argparse import subprocess import importlib.util from getpass import getpass +from distutils.dir_util import copy_tree, remove_tree from jinja2 import Environment, FileSystemLoader, select_autoescape -from .shell import check_output, silent_call -from .git import get_remote_origin, count_changes_from_remote +from ..shell import check_output, silent_call +from ..git import get_remote_origin, count_changes_from_remote def load_environment(template_path): @@ -229,7 +229,30 @@ def install(self, *, template, origin, user=None, token=None, branch='main'): subprocess.call(['git', 'checkout', '-b', branch]) subprocess.call(['git', 'pull', 'origin', branch]) subprocess.call(['git', 'branch', '--set-upstream-to=origin/%s'%branch, branch]) - + + def local_install(self, *, template:str, source:str, upgrade:bool): + + template_path = os.path.join(self.templates_directory, template) + + # ensure that --upgrade is used and the template directory exist + if (upgrade is True) and (os.path.isdir(template_path) is True): + self.remove(template=template) + + self.manifest.add_template(template) + os.makedirs(template_path) + + source_path = "" + + if source.startswith(".") is True: + source_path = os.path.abspath(source) + else: + source_path = source + + if os.path.isdir(source_path) is False: + raise NotADirectoryError() + + copy_tree(source_path, template_path) + print('template upgraded:' if upgrade is True else 'template installed', template) def update(self, template, verbose=False): template_path = os.path.join(self.templates_directory, template) @@ -253,7 +276,7 @@ def remove(self, template): try: template_path = os.path.join(self.templates_directory, template) self.manifest.remove_template(template) - shutil.rmtree(template_path) + remove_tree(template_path) except FileNotFoundError as e: print("[Warning] %s not found!"%template_path) print('template removed:', template) diff --git a/git_improved/templates/__init__.py b/git_improved/templates/__init__.py deleted file mode 100644 index 2bd44ab..0000000 --- a/git_improved/templates/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .python_package import PythonPackageTemplate - -TEMPLATES = { - 'python-package': PythonPackageTemplate -} diff --git a/git_improved/templates/python_package.py b/git_improved/templates/python_package.py deleted file mode 100644 index 138a023..0000000 --- a/git_improved/templates/python_package.py +++ /dev/null @@ -1,4 +0,0 @@ -from ..template import Template - -class PythonPackageTemplate(Template): - pass diff --git a/git_improved/workflow/__init__.py b/git_improved/workflow/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/git_improved/workflow/commands/__init__.py b/git_improved/workflow/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/git_improved/commands/cancel.py b/git_improved/workflow/commands/cancel.py similarity index 90% rename from git_improved/commands/cancel.py rename to git_improved/workflow/commands/cancel.py index 87f8e08..4ac7200 100644 --- a/git_improved/commands/cancel.py +++ b/git_improved/workflow/commands/cancel.py @@ -1,8 +1,8 @@ import argparse import subprocess -from ..menu import Menu -from ..command import Command -from ..git import get_local_branches, get_remote_branches, get_current_branch, delete_branch +from ...menu import Menu +from ...command import Command +from ...git import get_local_branches, get_remote_branches, get_current_branch, delete_branch def select_branches(): diff --git a/git_improved/commands/done.py b/git_improved/workflow/commands/done.py similarity index 94% rename from git_improved/commands/done.py rename to git_improved/workflow/commands/done.py index 9a3ae14..bc9f4fc 100644 --- a/git_improved/commands/done.py +++ b/git_improved/workflow/commands/done.py @@ -2,10 +2,10 @@ import uuid import argparse import subprocess -from ..command import Command -from ..constants import BRANCHES_PREFIXES, CATEGORIES_ICONS -from ..changelog import Changelog -from ..git import ( +from ...command import Command +from ...constants import BRANCHES_PREFIXES, CATEGORIES_ICONS +from ...changelog import Changelog +from ...git import ( get_current_branch, merge_squash, get_current_branch_commits, ensure_git_initialized, ensure_working_tree_clean, ensure_branch_mergeable ) diff --git a/git_improved/commands/release.py b/git_improved/workflow/commands/release.py similarity index 93% rename from git_improved/commands/release.py rename to git_improved/workflow/commands/release.py index 9bbb80d..7a65361 100644 --- a/git_improved/commands/release.py +++ b/git_improved/workflow/commands/release.py @@ -1,11 +1,11 @@ import re import argparse import subprocess -from ..command import Command -from ..changelog import Changelog -from ..constants import CATEGORIES_ICONS -from ..exceptions import ValidationError -from ..git import get_current_branch, ensure_main_branch +from ...command import Command +from ...changelog import Changelog +from ...constants import CATEGORIES_ICONS +from ...exceptions import ValidationError +from ...git import get_current_branch, ensure_main_branch # custom type used to parse semver diff --git a/git_improved/commands/save.py b/git_improved/workflow/commands/save.py similarity index 93% rename from git_improved/commands/save.py rename to git_improved/workflow/commands/save.py index 8702a17..7939d98 100644 --- a/git_improved/commands/save.py +++ b/git_improved/workflow/commands/save.py @@ -1,6 +1,6 @@ import argparse import subprocess -from ..command import Command +from ...command import Command class SaveCommand(metaclass=Command): diff --git a/git_improved/commands/unrelease.py b/git_improved/workflow/commands/unrelease.py similarity index 88% rename from git_improved/commands/unrelease.py rename to git_improved/workflow/commands/unrelease.py index 3c4032d..4e4c222 100644 --- a/git_improved/commands/unrelease.py +++ b/git_improved/workflow/commands/unrelease.py @@ -1,11 +1,11 @@ import re import argparse import subprocess -from ..git import get_releases -from ..menu import Menu -from ..command import Command -from ..changelog import Changelog -from ..exceptions import ValidationError +from ...git import get_releases +from ...menu import Menu +from ...command import Command +from ...changelog import Changelog +from ...exceptions import ValidationError def delete_release(version): diff --git a/git_improved/commands/wip.py b/git_improved/workflow/commands/wip.py similarity index 93% rename from git_improved/commands/wip.py rename to git_improved/workflow/commands/wip.py index 1ca8de7..bc79a42 100644 --- a/git_improved/commands/wip.py +++ b/git_improved/workflow/commands/wip.py @@ -1,7 +1,7 @@ import argparse import subprocess -from ..command import Command -from ..constants import BRANCHES_PREFIXES +from ...command import Command +from ...constants import BRANCHES_PREFIXES class WipCommand(metaclass=Command): diff --git a/setup.py b/setup.py index 111625f..96b5c06 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ import setuptools -from git_improved.constants import GITHUB_ICONS_URLS +from src.git_improved.constants import GITHUB_ICONS_URLS def load_long_description(): @@ -16,20 +16,20 @@ def load_long_description(): name='git-improved', description='Add commands to simplify release and publish operation from Git CLI.', version='0.1.5', - packages=setuptools.find_packages(), + packages=setuptools.find_packages(exclude=("tests")), entry_points={ 'console_scripts': [ - 'git-setup=git_improved.commands.setup:SetupCommand', - 'git-template=git_improved.commands.template:TemplateCommand', + #'git-setup=git_improved.commands.setup:SetupCommand', + #'git-template=git_improved.commands.template:TemplateCommand', - 'git-wip=git_improved.commands.wip:WipCommand', - 'git-save=git_improved.commands.save:SaveCommand', + 'git-wip=git_improved.workflow.commands.wip:WipCommand', + 'git-save=git_improved.workflow.commands.save:SaveCommand', - 'git-cancel=git_improved.commands.cancel:CancelCommand', - 'git-done=git_improved.commands.done:DoneCommand', + 'git-cancel=git_improved.workflow.commands.cancel:CancelCommand', + 'git-done=git_improved.workflow.commands.done:DoneCommand', - 'git-release=git_improved.commands.release:ReleaseCommand', - 'git-unrelease=git_improved.commands.unrelease:UnreleaseCommand' + 'git-release=git_improved.workflow.commands.release:ReleaseCommand', + 'git-unrelease=git_improved.workflow.commands.unrelease:UnreleaseCommand' ] }, install_requires=[