Completed
Push — master ( 56245b...a9d00e )
by
unknown
38s
created

is_zip_file()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
1
# -*- coding: utf-8 -*-
2
3
"""Cookiecutter repository functions."""
4
5
from __future__ import unicode_literals
6
import os
7
import re
8
9
from .exceptions import RepositoryNotFound
10
from .vcs import clone
11
from .zipfile import unzip
12
13
REPO_REGEX = re.compile(r"""
14
(?x)
15
((((git|hg)\+)?(git|ssh|https?):(//)?)  # something like git:// ssh:// etc.
16
 |                                      # or
17
 (\w+@[\w\.]+)                          # something like user@...
18
)
19
""")
20
21
22
def is_repo_url(value):
23
    """Return True if value is a repository URL."""
24
    return bool(REPO_REGEX.match(value))
25
26
27
def is_zip_file(value):
28
    """Return True if value is a zip file."""
29
    return value.lower().endswith('.zip')
30
31
32
def expand_abbreviations(template, abbreviations):
33
    """Expand abbreviations in a template name.
34
35
    :param template: The project template name.
36
    :param abbreviations: Abbreviation definitions.
37
    """
38
    if template in abbreviations:
39
        return abbreviations[template]
40
41
    # Split on colon. If there is no colon, rest will be empty
42
    # and prefix will be the whole template
43
    prefix, sep, rest = template.partition(':')
44
    if prefix in abbreviations:
45
        return abbreviations[prefix].format(rest)
46
47
    return template
48
49
50
def repository_has_cookiecutter_json(repo_directory):
51
    """Determine if `repo_directory` contains a `cookiecutter.json` file.
52
53
    :param repo_directory: The candidate repository directory.
54
    :return: True if the `repo_directory` is valid, else False.
55
    """
56
    repo_directory_exists = os.path.isdir(repo_directory)
57
58
    repo_config_exists = os.path.isfile(
59
        os.path.join(repo_directory, 'cookiecutter.json')
60
    )
61
    return repo_directory_exists and repo_config_exists
62
63
64
def determine_repo_dir(template, abbreviations, clone_to_dir, checkout,
65
                       no_input, password=None):
66
    """
67
    Locate the repository directory from a template reference.
68
69
    Applies repository abbreviations to the template reference.
70
    If the template refers to a repository URL, clone it.
71
    If the template is a path to a local repository, use it.
72
73
    :param template: A directory containing a project template directory,
74
        or a URL to a git repository.
75
    :param abbreviations: A dictionary of repository abbreviation
76
        definitions.
77
    :param clone_to_dir: The directory to clone the repository into.
78
    :param checkout: The branch, tag or commit ID to checkout after clone.
79
    :param no_input: Prompt the user at command line for manual configuration?
80
    :param password: The password to use when extracting the repository.
81
    :return: A tuple containing the cookiecutter template directory, and
82
        a boolean descriving whether that directory should be cleaned up
83
        after the template has been instantiated.
84
    :raises: `RepositoryNotFound` if a repository directory could not be found.
85
    """
86
    template = expand_abbreviations(template, abbreviations)
87
88
    if is_zip_file(template):
89
        unzipped_dir = unzip(
90
            zip_uri=template,
91
            is_url=is_repo_url(template),
92
            clone_to_dir=clone_to_dir,
93
            no_input=no_input,
94
            password=password
95
        )
96
        repository_candidates = [unzipped_dir]
97
        cleanup = True
98
    elif is_repo_url(template):
99
        cloned_repo = clone(
100
            repo_url=template,
101
            checkout=checkout,
102
            clone_to_dir=clone_to_dir,
103
            no_input=no_input,
104
        )
105
        repository_candidates = [cloned_repo]
106
        cleanup = False
107
    else:
108
        repository_candidates = [
109
            template,
110
            os.path.join(clone_to_dir, template)
111
        ]
112
        cleanup = False
113
114
    for repo_candidate in repository_candidates:
115
        if repository_has_cookiecutter_json(repo_candidate):
116
            return repo_candidate, cleanup
117
118
    raise RepositoryNotFound(
119
        'A valid repository for "{}" could not be found in the following '
120
        'locations:\n{}'.format(
121
            template,
122
            '\n'.join(repository_candidates)
123
        )
124
    )
125