Completed
Pull Request — master (#961)
by
unknown
01:20
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 repository URL."""
29
    return value.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):
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
    :return: The cookiecutter template directory
81
    :raises: `RepositoryNotFound` if a repository directory could not be found.
82
    """
83
    template = expand_abbreviations(template, abbreviations)
84
85
    if is_zip_file(template):
86
        unzipped_dir = unzip(
87
            zip_url=template,
88
            is_url=is_repo_url(template),
89
            clone_to_dir=clone_to_dir,
90
            no_input=no_input
91
        )
92
        repository_candidates = [unzipped_dir]
93
    elif is_repo_url(template):
94
        cloned_repo = clone(
95
            repo_url=template,
96
            checkout=checkout,
97
            clone_to_dir=clone_to_dir,
98
            no_input=no_input,
99
        )
100
        repository_candidates = [cloned_repo]
101
    else:
102
        repository_candidates = [
103
            template,
104
            os.path.join(clone_to_dir, template)
105
        ]
106
107
    for repo_candidate in repository_candidates:
108
        if repository_has_cookiecutter_json(repo_candidate):
109
            return repo_candidate
110
111
    raise RepositoryNotFound(
112
        'A valid repository for "{}" could not be found in the following '
113
        'locations:\n{}'.format(
114
            template,
115
            '\n'.join(repository_candidates)
116
        )
117
    )
118