Completed
Push — improve-repository-handling ( 491d70 )
by Michael
01:52
created

resolve_repo_dir()   B

Complexity

Conditions 5

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
c 1
b 0
f 0
dl 0
loc 41
rs 8.0894
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
"""
5
cookiecutter.repository
6
-----------------------
7
"""
8
9
from __future__ import unicode_literals
10
import logging
11
import os
12
import re
13
14
from .exceptions import RepositoryNotFound
15
from .vcs import clone
16
17
18
logger = logging.getLogger(__name__)
19
20
builtin_abbreviations = {
21
    'gh': 'https://github.com/{0}.git',
22
    'bb': 'https://bitbucket.org/{0}',
23
}
24
25
REPO_REGEX = re.compile(r"""
26
(?x)
27
((((git|hg)\+)?(git|ssh|https?):(//)?)  # something like git:// ssh:// etc.
28
 |                                      # or
29
 (\w+@[\w\.]+)                          # something like user@...
30
)
31
""")
32
33
34
def is_repo_url(value):
35
    """Return True if value is a repository URL."""
36
    return bool(REPO_REGEX.match(value))
37
38
39
def expand_abbreviations(template, config_dict):
40
    """
41
    Expand abbreviations in a template name.
42
43
    :param template: The project template name.
44
    :param config_dict: The user config, which will contain abbreviation
45
        definitions.
46
    """
47
48
    abbreviations = builtin_abbreviations.copy()
49
    abbreviations.update(config_dict.get('abbreviations', {}))
50
51
    if template in abbreviations:
52
        return abbreviations[template]
53
54
    # Split on colon. If there is no colon, rest will be empty
55
    # and prefix will be the whole template
56
    prefix, sep, rest = template.partition(':')
57
    if prefix in abbreviations:
58
        return abbreviations[prefix].format(rest)
59
60
    return template
61
62
63
def resolve_repo_dir(template, checkout, cookiecutters_dir, no_input):
64
    """
65
    Given a template reference, resolve this into a directory containing
66
    the repository.
67
68
    :param template: A URL to a git repository, a directory containing a
69
        project template directory, or an already cloned cookiecutter.
70
    :param checkout: The branch, tag or commit ID to checkout after clone.
71
    :param cookiecutters_dir: The directory storing cookiecutters.
72
    :param no_input: Prompt the user at command line for manual configuration?
73
    """
74
    repo_dir = None
75
76
    already_cloned_cookiecutter = os.path.normpath(os.path.join(
77
        cookiecutters_dir,
78
        template
79
    ))
80
81
    if is_repo_url(template):
82
        repo_dir = clone(
83
            repo_url=template,
84
            checkout=checkout,
85
            clone_to_dir=cookiecutters_dir,
86
            no_input=no_input
87
        )
88
    elif os.path.isdir(template):
89
        # If it's a local repo, no need to clone or copy to your
90
        # cookiecutters_dir
91
        repo_dir = template
92
    elif os.path.isdir(already_cloned_cookiecutter):
93
        repo_dir = already_cloned_cookiecutter
94
95
    if repo_dir is None:
96
        raise RepositoryNotFound(
97
            'The repository {0} could not be located.'.format(template)
98
        )
99
100
    logging.debug('Using cookiecutter repository {}'.format(
101
        os.path.abspath(repo_dir)
102
    ))
103
    return repo_dir
104