From 1575368c5e888a08677bd527e9d2559896bd8d44 Mon Sep 17 00:00:00 2001 From: nathanurwin Date: Thu, 15 Mar 2018 08:49:01 -0500 Subject: [PATCH] Fix for (#15);Update package_name key to make_dirs;Add python3 support --- .gitignore | 171 +++++++++++++ AUTHORS.md | 2 +- CHANGELOG.md | 28 +-- CONTRIBUTING.md | 4 +- LICENSE | 2 +- README.md | 25 +- cookiecutter.json | 24 +- hooks/post_gen_project.py | 234 ++++++++++-------- .../.editorconfig | 0 .../.gitignore | 94 +++---- .../AUTHORS.md | 0 .../CHANGELOG.md | 0 .../CONTRIBUTING.md | 4 +- .../LICENSES/AGPL-3.0.txt | 0 .../LICENSES/Apache-2.0.txt | 0 .../LICENSES/BSD-2-Clause.txt | 0 .../LICENSES/BSD-3-Clause.txt | 0 .../LICENSES/EPL-1.0.txt | 0 .../LICENSES/GPL-2.0.txt | 0 .../LICENSES/GPL-3.0.txt | 0 .../LICENSES/LGPL-2.1.txt | 0 .../LICENSES/LGPL-3.0.txt | 0 .../LICENSES/MIT.txt | 0 .../LICENSES/MPL-2.0.txt | 0 .../LICENSES/Unlicense.txt | 0 .../NOTICE | 0 .../README.md | 4 +- .../{{cookiecutter.package_name}}/.gitkeep | 0 28 files changed, 401 insertions(+), 191 deletions(-) create mode 100644 .gitignore rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/.editorconfig (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/.gitignore (82%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/AUTHORS.md (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/CHANGELOG.md (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/CONTRIBUTING.md (64%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/AGPL-3.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/Apache-2.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/BSD-2-Clause.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/BSD-3-Clause.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/EPL-1.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/GPL-2.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/GPL-3.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/LGPL-2.1.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/LGPL-3.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/MIT.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/MPL-2.0.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/LICENSES/Unlicense.txt (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/NOTICE (100%) rename {{{cookiecutter.repository_slug}} => {{cookiecutter.repo_slug}}}/README.md (76%) delete mode 100644 {{cookiecutter.repository_slug}}/{{cookiecutter.package_name}}/.gitkeep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bc4379 --- /dev/null +++ b/.gitignore @@ -0,0 +1,171 @@ + +# Created by https://www.gitignore.io/api/windows,macos,linux,git,python + +### Git ### +*.orig + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +.pytest_cache/ +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule.* + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +# End of https://www.gitignore.io/api/windows,macos,linux,git,python diff --git a/AUTHORS.md b/AUTHORS.md index 03365cc..7843e96 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1,7 +1,7 @@ # Authors ## Project Lead -[Nathan Urwin](https://github.com/tuxredux) <tuxredux2@gmail.com> +[Nathan Urwin](https://github.com/nathanurwin) <nathan.e.urwin@gmail.com> ## Contributors None yet. [Why not be the first?](CONTRIBUTING.md) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b29cf..c88a0e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,32 @@ # Change Log -## [v0.3.0](https://github.com/webevllc/cookiecutter-git/tree/v0.3.0) (2017-03-25) -[Full Changelog](https://github.com/webevllc/cookiecutter-git/compare/v0.2.0...v0.3.0) +## [v0.3.0](https://github.com/nathanurwin/cookiecutter-git/tree/v0.3.0) (2017-03-25) +[Full Changelog](https://github.com/nathanurwin/cookiecutter-git/compare/v0.2.0...v0.3.0) **Implemented enhancements:** -- Add cookiecutter.json documentation [\#14](https://github.com/webevllc/cookiecutter-git/issues/14) -- Refactor cookiecutter.json keys [\#13](https://github.com/webevllc/cookiecutter-git/issues/13) +- Add cookiecutter.json documentation [\#14](https://github.com/nathanurwin/cookiecutter-git/issues/14) +- Refactor cookiecutter.json keys [\#13](https://github.com/nathanurwin/cookiecutter-git/issues/13) -## [v0.2.0](https://github.com/webevllc/cookiecutter-git/tree/v0.2.0) (2017-03-24) -[Full Changelog](https://github.com/webevllc/cookiecutter-git/compare/v0.1.0...v0.2.0) +## [v0.2.0](https://github.com/nathanurwin/cookiecutter-git/tree/v0.2.0) (2017-03-24) +[Full Changelog](https://github.com/nathanurwin/cookiecutter-git/compare/v0.1.0...v0.2.0) **Implemented enhancements:** -- Bitbucket.org support [\#5](https://github.com/webevllc/cookiecutter-git/issues/5) -- First tagged release [\#3](https://github.com/webevllc/cookiecutter-git/issues/3) +- Bitbucket.org support [\#5](https://github.com/nathanurwin/cookiecutter-git/issues/5) +- First tagged release [\#3](https://github.com/nathanurwin/cookiecutter-git/issues/3) -## [v0.1.0](https://github.com/webevllc/cookiecutter-git/tree/v0.1.0) (2017-03-24) +## [v0.1.0](https://github.com/nathanurwin/cookiecutter-git/tree/v0.1.0) (2017-03-24) **Implemented enhancements:** -- More license choices [\#4](https://github.com/webevllc/cookiecutter-git/issues/4) -- Use github-changelog-generator [\#2](https://github.com/webevllc/cookiecutter-git/issues/2) -- Gitlab.com support [\#1](https://github.com/webevllc/cookiecutter-git/issues/1) +- More license choices [\#4](https://github.com/nathanurwin/cookiecutter-git/issues/4) +- Use github-changelog-generator [\#2](https://github.com/nathanurwin/cookiecutter-git/issues/2) +- Gitlab.com support [\#1](https://github.com/nathanurwin/cookiecutter-git/issues/1) **Fixed bugs:** -- Insecure gitlab\_token retrieval [\#6](https://github.com/webevllc/cookiecutter-git/issues/6) +- Insecure gitlab\_token retrieval [\#6](https://github.com/nathanurwin/cookiecutter-git/issues/6) -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8977d45..9323b8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,6 @@ Make sure to have atomic commits and contextual commit messages! [Check out this awesome blog post by Chris Beams for more information.][3] -[1]: https://github.com/tuxredux/cookiecutter-git/issues/new -[2]: https://github.com/tuxredux/cookiecutter-git/compare +[1]: https://github.com/nathanurwin/cookiecutter-git/issues/new +[2]: https://github.com/nathanurwin/cookiecutter-git/compare [3]: http://chris.beams.io/posts/git-commit/ diff --git a/LICENSE b/LICENSE index 801ca37..b2044d3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Nathan Urwin +Copyright (c) 2018 Nathan Urwin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index e9facb3..4c97e97 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # cookiecutter-git A git repository project template! +### Table of Contents - [Features](#features) - [Upcoming](#upcoming) - [Requirements](#requirements) @@ -13,7 +14,7 @@ A git repository project template! - [License](#license) ## Features -- [Bare project structure](https://github.com/tuxredux/cookiecutter-git-example) +- [Bare project structure](https://github.com/nathanurwin/cookiecutter-git-example) - For any programming language or codebase - Useful but not overruling organization - [License customization](https://developer.github.com/v3/licenses/) @@ -37,31 +38,31 @@ A git repository project template! - [cookiecutter](https://github.com/audreyr/cookiecutter) ## Usage - $ cookiecutter gh:tuxredux/cookiecutter-git + $ cookiecutter gh:nathanurwin/cookiecutter-git Which is an alias for: - $ cookiecutter https://github.com/tuxredux/cookiecutter-git + $ cookiecutter https://github.com/nathanurwin/cookiecutter-git -See generated [README.md]({{cookiecutter.repository_slug}}/README.md) +See generated [README.md]({{cookiecutter.repo_slug}}/README.md) ### Example -See [cookiecutter-git-example](https://github.com/tuxredux/cookiecutter-git-example) +See [cookiecutter-git-demo](https://github.com/nathanurwin/cookiecutter-git-demo) - $ tree -a -I .git cookiecutter-git-example + $ tree -a -I .git cookiecutter-git-demo cookiecutter-git-example ├── AUTHORS.md ├── CHANGELOG.md ├── CONTRIBUTING.md - ├── .editorconfig └── example_package │  └── .gitkeep + ├── .editorconfig ├── .gitignore ├── LICENSE ├── NOTICE └── README.md - 1 directories, 9 files + 3 directories, 9 files ## Documentation **cookiecutter.json** explained in-depth. See [cookiecutter.json](cookiecutter.json) for default values. @@ -71,10 +72,10 @@ Prompt | Explanation `author_name` | Your full name, including first and last names, titles, and possibly even your middle name. This will go under *Project Lead* in **AUTHORS.md**. `author_email` | The email address you want associated with the repository. This will go under *Project Lead* in **AUTHORS.md**. `git_username` | Your local git and `remote_provider` (see below) account username. This will be used for all git-based actions. -`repository_namespace` | The namespace where the repository will live, which can be a user or organization, group, or team (depending on the `remote_provider`). This will only be used if `create_remote` (see below) is `yes`. -`repository_slug` | The repository name which should only contain alphanumeric characters and dashes. This will be the local, top-level directory name, the remote endpoint, and the *H1* in the **README.md**. -`repository_description` | A short description about the repository. This will be the remote description setting, and the content under the *H1* in the **README.md**. -`package_name` | The child directory name. This will be dependent on your codebase. For example, the default value contains only alphanumeric characters and underscores suitable for [python development](https://www.python.org/dev/peps/pep-0008/). +`repo_namespace` | The namespace where the repository will live, which can be a user or organization, group, or team (depending on the `remote_provider`). This will only be used if `create_remote` (see below) is `yes`. +`repo_slug` | The repository name which should only contain alphanumeric characters and dashes. This will be the local, top-level directory name, the remote endpoint, and the *H1* in the **README.md**. +`repo_description` | A short description about the repository. This will be the remote description setting, and the content under the *H1* in the **README.md**. +`make_dirs` | A comma-separated values list of directory names. These will be made with a `.gitkeep` file, so the dirs will be added to the initial commit. `create_remote` | A `yes` or `no` choice on whether or not a remote repository is automatically created for you. This option is the main reason for *cookiecutter-git*, so the default choice is `yes`. `remote_provider` | A choice between the three main, git, remote repository providers. This will only be used if `create_remote` is `yes`, and defaults to `github.com`. `gitignore` | A comma-separated values list of preset templates of files for git to ignore. See the [gitignore.io docs](https://github.com/joeblau/gitignore.io#list) for a complete list of available values. This will be used to generate the **.gitignore** file. diff --git a/cookiecutter.json b/cookiecutter.json index 2fa01d9..73041bc 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -1,25 +1,25 @@ { "author_name": "Nathan Urwin", - "author_email": "tuxredux2@gmail.com", - "git_username": "tuxredux", - "repository_namespace": "tuxredux", - "repository_slug": "cookiecutter-git-example", - "repository_description": "An example cookiecutter-git project", - "package_name": "example_package", - "create_remote": ["yes", "no"], + "author_email": "nathan.e.urwin@gmail.com", + "git_username": "nathanurwin", + "repo_namespace": "nathanurwin", + "repo_slug": "cookiecutter-git-demo", + "repo_description": "A cookiecutter-git demonstration", + "make_dirs": "docs,src,tests", + "create_remote": ["no", "yes", "no"], "remote_provider": ["github.com", "gitlab.com", "bitbucket.org"], - "gitignore": "windows,osx,linux,git", + "gitignore": "windows,macos,linux,git", "license": [ - "Apache-2.0", - "GPL-3.0", "MIT", + "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", - "EPL-1.0", - "AGPL-3.0", "GPL-2.0", + "GPL-3.0", + "AGPL-3.0", "LGPL-2.1", "LGPL-3.0", + "EPL-1.0", "MPL-2.0", "Unlicense" ], diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 79520e7..989b69b 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -1,54 +1,32 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, with_statement +"""Cookiecutter-Git Post-Generate Project Hook. +""" -from __future__ import print_function - -import os -import json +import base64 import codecs +import errno +import json +import os import shutil -import base64 -import urllib -import urllib2 + import getpass import subprocess - -REPO_PATH = os.getcwd() -LICENSES_DIRPATH = os.path.join(REPO_PATH, 'LICENSES') -LICENSE_TXT = os.path.join(LICENSES_DIRPATH, '{{cookiecutter.license}}.txt') -LICENSE_PATH = os.path.join(REPO_PATH, 'LICENSE') -NOTICE_PATH = os.path.join(REPO_PATH, 'NOTICE') -GITIGNORE_PATH = os.path.join(REPO_PATH, '.gitignore') -GITIGNORE_URL = 'https://www.gitignore.io/api/{{cookiecutter.gitignore}}' -JSON_HEADER = {'Content-Type': 'application/json; charset=utf-8'} - -BITBUCKET_REPOS_URL = ('https://api.bitbucket.org/2.0/repositories/' - '{{cookiecutter.repository_namespace}}/{{cookiecutter.repository_slug}}') - -{% if cookiecutter.git_username == cookiecutter.repository_namespace %} -GITHUB_REPOS_URL = 'https://api.github.com/user/repos' -{% else %} -GITHUB_REPOS_URL = ('https://api.github.com/orgs/' - '{{cookiecutter.repository_namespace}}/repos') -{% endif %} - -{% if cookiecutter.create_remote == 'yes' and cookiecutter.remote_provider == 'gitlab.com' %} -GITLAB_TOKEN = getpass.getpass('gitlab_token: ').strip() -GITLAB_TOKEN_HEADER = {'PRIVATE-TOKEN': GITLAB_TOKEN} -{% endif %} -GITLAB_NAMESPACES_URL = 'https://gitlab.com/api/v3/namespaces' -GITLAB_PROJECTS_URL = 'https://gitlab.com/api/v3/projects' - -REMOTE_REPO_URL = ('https://{{cookiecutter.git_username}}@' - '{{cookiecutter.remote_provider}}/{{cookiecutter.repository_namespace}}/' - '{{cookiecutter.repository_slug}}.git') -REMOTE_REPO_DATA = { - 'name': '{{cookiecutter.repository_slug}}', - 'description': '{{cookiecutter.repository_description}}' - } +try: + # python 2 + from urllib import urlencode + from urllib2 import HTTPError, Request, urlopen +except ImportError: + # python3 + from urllib.error import HTTPError + from urllib.parse import urlencode + from urllib.request import Request, urlopen def run(command, log=True): + """A quick-and-dirty function that mimicks the fabric library local run. + """ try: output = codecs.decode(subprocess.check_output(command), 'utf-8') except subprocess.CalledProcessError as error: @@ -63,15 +41,19 @@ def run(command, log=True): class requests(object): + """ A class that mimicks the requests library using the built-in urllib. + """ @staticmethod def _request(url, headers, data, log): + """A quick-and-dirty static method that wraps the urllib Request class. + """ try: - req = urllib2.Request(url, data=data, headers=headers) - response = urllib2.urlopen(req) + req = Request(url, data=data, headers=headers) + response = urlopen(req) content = response.read() response.close() - except urllib2.HTTPError as error: + except HTTPError as error: message = error.read() error.close() args = (error.code, error.reason, url, message) @@ -86,65 +68,55 @@ def _request(url, headers, data, log): @classmethod def get(cls, url, headers={}, log=True): + """A basic http GET request wrapper class method. + """ return cls._request(url, headers, None, log) @classmethod def post(cls, url, headers={}, data=None, log=True): + """A basic http POST request wrapper class method. + """ return cls._request(url, headers, data, log) +# Constants +GITHUB_REPOS_URL = 'https://api.github.com/user/repos' +GITLAB_NAMESPACES_URL = 'https://gitlab.com/api/v3/namespaces' +GITLAB_PROJECTS_URL = 'https://gitlab.com/api/v3/projects' +JSON_HEADER = {'Content-Type': 'application/json; charset=utf-8'} -def create_remote_repo(): - {% if cookiecutter.remote_provider == 'github.com' %} - data = json.dumps(REMOTE_REPO_DATA) - prompt = ("Password for 'https://{{cookiecutter.git_username}}@" - "{{cookiecutter.remote_provider}}': ") - auth_info = ('{{cookiecutter.git_username}}', - getpass.getpass(prompt).strip()) - auth_base = base64.b64encode('{}:{}'.format(*auth_info)) - headers = {'Authorization': 'Basic {}'.format(auth_base)} - requests.post(GITHUB_REPOS_URL, data=data, headers=headers) - - {% elif cookiecutter.remote_provider == 'gitlab.com' %} - search_param = {'search': '{{cookiecutter.repository_namespace}}'} - search_url = GITLAB_NAMESPACES_URL + '?' + urllib.urlencode(search_param) - search_results = requests.get(search_url, headers=GITLAB_TOKEN_HEADER) - gitlab_namespaces = json.loads(search_results) - for namespace in gitlab_namespaces: - if namespace.get('path', '') == '{{cookiecutter.repository_namespace}}': - namespace_id = namespace.get('id', '') - if namespace_id: - REMOTE_REPO_DATA.update({'namespace_id': namespace_id}) - data = urllib.urlencode(REMOTE_REPO_DATA) - requests.post(GITLAB_PROJECTS_URL, data=data, headers=GITLAB_TOKEN_HEADER) - - {% elif cookiecutter.remote_provider == 'bitbucket.org' %} - REMOTE_REPO_DATA.update({'has_issues': True, 'is_private': True}) - data = json.dumps(REMOTE_REPO_DATA) - prompt = ("Password for 'https://{{cookiecutter.git_username}}@" - "{{cookiecutter.remote_provider}}': ") - auth_info = ('{{cookiecutter.git_username}}', - getpass.getpass(prompt).strip()) - auth_base = base64.b64encode('{}:{}'.format(*auth_info)) - JSON_HEADER['Authorization'] = 'Basic {}'.format(auth_base) - requests.post(BITBUCKET_REPOS_URL, data=data, headers=JSON_HEADER) - {% endif %} - - -def setup_license_file(): - {% if cookiecutter.license != 'Apache-2.0' %} - print("Removing '{}'...".format(NOTICE_PATH)) - os.remove(NOTICE_PATH) - {% endif %} - shutil.move(LICENSE_TXT, LICENSE_PATH) - shutil.rmtree(LICENSES_DIRPATH, ignore_errors=True) +# Globals +REPO_PATH = os.getcwd() +APACHE_LICENSE = {% if cookiecutter.license == 'Apache-2.0' %}True{% else %}False{% endif %} +BITBUCKET_REPOS_URL = 'https://api.bitbucket.org/2.0/repositories/{{cookiecutter.repo_namespace}}/{{cookiecutter.repo_slug}}' +CREATE_REMOTE = {% if cookiecutter.create_remote == 'yes' %}True{% else %}False{% endif %} +GITIGNORE_PATH = os.path.join(REPO_PATH, '.gitignore') +{% if cookiecutter.git_username != cookiecutter.repo_namespace %} +GITHUB_REPOS_URL = 'https://api.github.com/orgs/{{cookiecutter.repo_namespace}}/repos' +{% endif %} +GITIGNORE_URL = 'https://www.gitignore.io/api/{{cookiecutter.gitignore}}' +GIT_USERNAME = '{{cookiecutter.git_username}}' +LICENSES_DIRPATH = os.path.join(REPO_PATH, 'LICENSES') +LICENSE_PATH = os.path.join(REPO_PATH, 'LICENSE') +LICENSE_TXT = os.path.join(LICENSES_DIRPATH, '{{cookiecutter.license}}.txt') +NEW_GITIGNORE = {% if cookiecutter.gitignore != 'windows,macos,linux,git' %}True{% else %}False{% endif %} +NOTICE_PATH = os.path.join(REPO_PATH, 'NOTICE') +PASSWORD_PROMPT = "Password for 'https://{{cookiecutter.git_username}}@{{cookiecutter.remote_provider}}': " +PROJECT_DIRS = [os.path.join(REPO_PATH, dirname) for dirname in '{{cookiecutter.make_dirs}}'.split(',')] +REMOTE_DATA = {'name': '{{cookiecutter.repo_slug}}', 'description': '{{cookiecutter.repo_description}}'} +REPO_NAMESPACE = '{{cookiecutter.repo_namespace}}' +REMOTE_ORIGIN_URL = 'https://{{cookiecutter.git_username}}@{{cookiecutter.remote_provider}}/{{cookiecutter.repo_namespace}}/{{cookiecutter.repo_slug}}.git' +REMOTE_PROVIDER = '{{cookiecutter.remote_provider}}' +SUCCESS_MESSAGE = '\n{{cookiecutter.repo_slug}} setup successfully!\n\n' def setup_git_repo(): - {% if cookiecutter.gitignore != 'windows,osx,linux,git' %} - with open(GITIGNORE_PATH, 'wb') as f: - f.write(requests.get(GITIGNORE_URL)) - print("updated '{}'".format(GITIGNORE_PATH)) - {% endif %} + """A function that adds a .gitignore, initial commit, and remote repo. + """ + if NEW_GITIGNORE: + response = requests.get(GITIGNORE_URL) + with open(GITIGNORE_PATH, 'wb') as f: + f.write(response) + print("updated '{}'".format(GITIGNORE_PATH)) run(['git', 'init']) run(['git', 'status']) @@ -152,18 +124,80 @@ def setup_git_repo(): run(['git', 'status']) run(['git', 'commit', '-m', 'Initial commit']) - {% if cookiecutter.create_remote == 'yes' %} - create_remote_repo() - run(['git', 'remote', 'add', 'origin', REMOTE_REPO_URL]) - run(['git', 'push', '-u', 'origin', 'master']) - {% endif %} + if CREATE_REMOTE: + auth_info = (GIT_USERNAME, getpass.getpass(PASSWORD_PROMPT).strip()) + auth_base = base64.b64encode('{}:{}'.format(*auth_info)) + + if REMOTE_PROVIDER == 'github.com': + create_remote_url = GITHUB_REPOS_URL + data = json.dumps(REMOTE_DATA) + headers = {'Authorization': 'Basic {}'.format(auth_base)} + + elif REMOTE_PROVIDER == 'gitlab.com': + gitlab_token = getpass.getpass('gitlab_token: ').strip() + token_header = {'PRIVATE-TOKEN': gitlab_token} + search_param = {'search': REPO_NAMESPACE} + search_url = GITLAB_NAMESPACES_URL + '?' + urlencode(search_param) + search_results = requests.get(search_url, headers=token_header) + gitlab_namespaces = json.loads(search_results) + for namespace in gitlab_namespaces: + if namespace.get('path', '') == REPO_NAMESPACE: + namespace_id = namespace.get('id', '') + if namespace_id: + REMOTE_DATA.update({'namespace_id': namespace_id}) + + create_remote_url = GITLAB_PROJECTS_URL + data = urlencode(REMOTE_DATA) + headers = token_header + + elif REMOTE_PROVIDER == 'bitbucket.org': + REMOTE_DATA.update({'has_issues': True, 'is_private': True}) + JSON_HEADER['Authorization'] = 'Basic {}'.format(auth_base) + + create_remote_url = BITBUCKET_REPOS_URL + data = json.dumps(REMOTE_DATA) + headers = JSON_HEADER + + requests.post(create_remote_url, data=data, headers=headers) + run(['git', 'remote', 'add', 'origin', REMOTE_ORIGIN_URL]) + run(['git', 'push', '-u', 'origin', 'master']) + + +def setup_project_dirs(): + """A function that makes dirs and adds .gitkeep files to them. + """ + for dirpath in PROJECT_DIRS: + try: + os.makedirs(dirpath) + except OSError as exc: + if exc.errno == errno.EEXIST and os.path.isdir(dirpath): + pass + else: + raise + gitkeep = os.path.join(dirpath, '.gitkeep') + with open(gitkeep, 'a'): + os.utime(gitkeep, None) + + +def setup_license_file(): + """A simple function that adds the chosen LICENSE and removes the rest. + """ + if not APACHE_LICENSE: + print("Removing '{}'...".format(NOTICE_PATH)) + os.remove(NOTICE_PATH) + + shutil.move(LICENSE_TXT, LICENSE_PATH) + shutil.rmtree(LICENSES_DIRPATH, ignore_errors=True) def main(): + """The main entry point for the post-generate project hook. + """ setup_license_file() + setup_project_dirs() setup_git_repo() - print('\n{{cookiecutter.repository_slug}} setup successfully!\n\n') - + print(SUCCESS_MESSAGE) +# This is required! Don't remove!! if __name__ == '__main__': main() diff --git a/{{cookiecutter.repository_slug}}/.editorconfig b/{{cookiecutter.repo_slug}}/.editorconfig similarity index 100% rename from {{cookiecutter.repository_slug}}/.editorconfig rename to {{cookiecutter.repo_slug}}/.editorconfig diff --git a/{{cookiecutter.repository_slug}}/.gitignore b/{{cookiecutter.repo_slug}}/.gitignore similarity index 82% rename from {{cookiecutter.repository_slug}}/.gitignore rename to {{cookiecutter.repo_slug}}/.gitignore index 16b427e..0af105d 100644 --- a/{{cookiecutter.repository_slug}}/.gitignore +++ b/{{cookiecutter.repo_slug}}/.gitignore @@ -1,10 +1,56 @@ -# Created by https://www.gitignore.io/api/windows,osx,linux,git +# Created by https://www.gitignore.io/api/windows,macos,linux,git + +### Git ### +*.orig + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk ### Windows ### -# Windows image file caches +# Windows thumbnail cache files Thumbs.db ehthumbs.db +ehthumbs_vista.db # Folder config file Desktop.ini @@ -22,46 +68,4 @@ $RECYCLE.BIN/ *.lnk -### OSX ### -*.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon -# Thumbnails -._* -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - - -### Git ### -*.orig +# End of https://www.gitignore.io/api/windows,macos,linux,git diff --git a/{{cookiecutter.repository_slug}}/AUTHORS.md b/{{cookiecutter.repo_slug}}/AUTHORS.md similarity index 100% rename from {{cookiecutter.repository_slug}}/AUTHORS.md rename to {{cookiecutter.repo_slug}}/AUTHORS.md diff --git a/{{cookiecutter.repository_slug}}/CHANGELOG.md b/{{cookiecutter.repo_slug}}/CHANGELOG.md similarity index 100% rename from {{cookiecutter.repository_slug}}/CHANGELOG.md rename to {{cookiecutter.repo_slug}}/CHANGELOG.md diff --git a/{{cookiecutter.repository_slug}}/CONTRIBUTING.md b/{{cookiecutter.repo_slug}}/CONTRIBUTING.md similarity index 64% rename from {{cookiecutter.repository_slug}}/CONTRIBUTING.md rename to {{cookiecutter.repo_slug}}/CONTRIBUTING.md index 3f0c091..4b58b5a 100644 --- a/{{cookiecutter.repository_slug}}/CONTRIBUTING.md +++ b/{{cookiecutter.repo_slug}}/CONTRIBUTING.md @@ -16,6 +16,6 @@ Make sure to have atomic commits and contextual commit messages! [Check out this awesome blog post by Chris Beams for more information.][3] -[1]: https://{{cookiecutter.remote_provider}}/{{cookiecutter.repository_namespace}}/{{cookiecutter.repository_slug}}/issues/new -[2]: https://github.com/{{cookiecutter.repository_namespace}}/{{cookiecutter.repository_slug}}/{% if cookiecutter.remote_provider == 'github.com' %}compare{% elif cookiecutter.remote_provider == 'gitlab.com' %}merge_requests/new{% elif cookiecutter.remote_provider == 'bitbucket.org' %}pull-requests/new{% endif %} +[1]: https://{{cookiecutter.remote_provider}}/{{cookiecutter.repo_namespace}}/{{cookiecutter.repo_slug}}/issues/new +[2]: https://github.com/{{cookiecutter.repo_namespace}}/{{cookiecutter.repo_slug}}/{% if cookiecutter.remote_provider == 'github.com' %}compare{% elif cookiecutter.remote_provider == 'gitlab.com' %}merge_requests/new{% elif cookiecutter.remote_provider == 'bitbucket.org' %}pull-requests/new{% endif %} [3]: http://chris.beams.io/posts/git-commit/ diff --git a/{{cookiecutter.repository_slug}}/LICENSES/AGPL-3.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/AGPL-3.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/AGPL-3.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/AGPL-3.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/Apache-2.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/Apache-2.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/Apache-2.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/Apache-2.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/BSD-2-Clause.txt b/{{cookiecutter.repo_slug}}/LICENSES/BSD-2-Clause.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/BSD-2-Clause.txt rename to {{cookiecutter.repo_slug}}/LICENSES/BSD-2-Clause.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/BSD-3-Clause.txt b/{{cookiecutter.repo_slug}}/LICENSES/BSD-3-Clause.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/BSD-3-Clause.txt rename to {{cookiecutter.repo_slug}}/LICENSES/BSD-3-Clause.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/EPL-1.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/EPL-1.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/EPL-1.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/EPL-1.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/GPL-2.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/GPL-2.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/GPL-2.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/GPL-2.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/GPL-3.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/GPL-3.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/GPL-3.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/GPL-3.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/LGPL-2.1.txt b/{{cookiecutter.repo_slug}}/LICENSES/LGPL-2.1.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/LGPL-2.1.txt rename to {{cookiecutter.repo_slug}}/LICENSES/LGPL-2.1.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/LGPL-3.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/LGPL-3.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/LGPL-3.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/LGPL-3.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/MIT.txt b/{{cookiecutter.repo_slug}}/LICENSES/MIT.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/MIT.txt rename to {{cookiecutter.repo_slug}}/LICENSES/MIT.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/MPL-2.0.txt b/{{cookiecutter.repo_slug}}/LICENSES/MPL-2.0.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/MPL-2.0.txt rename to {{cookiecutter.repo_slug}}/LICENSES/MPL-2.0.txt diff --git a/{{cookiecutter.repository_slug}}/LICENSES/Unlicense.txt b/{{cookiecutter.repo_slug}}/LICENSES/Unlicense.txt similarity index 100% rename from {{cookiecutter.repository_slug}}/LICENSES/Unlicense.txt rename to {{cookiecutter.repo_slug}}/LICENSES/Unlicense.txt diff --git a/{{cookiecutter.repository_slug}}/NOTICE b/{{cookiecutter.repo_slug}}/NOTICE similarity index 100% rename from {{cookiecutter.repository_slug}}/NOTICE rename to {{cookiecutter.repo_slug}}/NOTICE diff --git a/{{cookiecutter.repository_slug}}/README.md b/{{cookiecutter.repo_slug}}/README.md similarity index 76% rename from {{cookiecutter.repository_slug}}/README.md rename to {{cookiecutter.repo_slug}}/README.md index 5e42381..4ebda4c 100644 --- a/{{cookiecutter.repository_slug}}/README.md +++ b/{{cookiecutter.repo_slug}}/README.md @@ -1,5 +1,5 @@ -# {{cookiecutter.repository_slug}} -{{cookiecutter.repository_description}} +# {{cookiecutter.repo_slug}} +{{cookiecutter.repo_description}} ## Development See [CONTRIBUTING](CONTRIBUTING.md) diff --git a/{{cookiecutter.repository_slug}}/{{cookiecutter.package_name}}/.gitkeep b/{{cookiecutter.repository_slug}}/{{cookiecutter.package_name}}/.gitkeep deleted file mode 100644 index e69de29..0000000