File: __init__.py

package info (click to toggle)
python-setuptools-git 1.2-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 136 kB
  • sloc: python: 492; makefile: 23
file content (140 lines) | stat: -rw-r--r-- 3,950 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""
A hook into setuptools for Git.
"""
import sys
import os
import posixpath

from os.path import realpath, join
from subprocess import PIPE

from setuptools_git.utils import check_output
from setuptools_git.utils import b
from setuptools_git.utils import posix
from setuptools_git.utils import fsdecode
from setuptools_git.utils import hfs_quote
from setuptools_git.utils import compose
from setuptools_git.utils import decompose
from setuptools_git.utils import CalledProcessError


def version_calc(dist, attr, value):
    """
    Handler for parameter to setup(use_vcs_version=value)
    bool(value) should be true to invoke this plugin.
    """
    if attr == 'use_vcs_version' and value:
        dist.metadata.version = calculate_version()


def calculate_version():
    return check_output(['git', 'describe', '--tags', '--dirty']).strip()


def ntfsdecode(path):
    # We receive the raw bytes from Git and must decode by hand
    if sys.version_info >= (3,):
        try:
            path = path.decode('utf-8')
        except UnicodeDecodeError:
            path = path.decode(sys.getfilesystemencoding())
    else:
        try:
            path = path.decode('utf-8').encode(sys.getfilesystemencoding())
        except UnicodeError:
            pass  # Already in filesystem encoding (hopefully)
    return path


def gitlsfiles(dirname=''):
    # NB: Passing the '-z' option to 'git ls-files' below returns the
    # output as a blob of null-terminated filenames without canonical-
    # ization or use of double-quoting.
    #
    # So we'll get back e.g.:
    #
    # 'pyramid/tests/fixtures/static/h\xc3\xa9h\xc3\xa9.html'
    #
    # instead of:
    #
    # '"pyramid/tests/fixtures/static/h\\303\\251h\\303\\251.html"'
    #
    # for each file.
    res = set()

    try:
        topdir = check_output(
            ['git', 'rev-parse', '--show-toplevel'], cwd=dirname or None,
            stderr=PIPE).strip()

        if sys.platform == 'win32':
            cwd = ntfsdecode(topdir)
        else:
            cwd = topdir

        filenames = check_output(
            ['git', 'ls-files', '-z'], cwd=cwd, stderr=PIPE)
    except (CalledProcessError, OSError):
        # Setuptools mandates we fail silently
        return res

    for filename in filenames.split(b('\x00')):
        if filename:
            filename = posixpath.join(topdir, filename)
            if sys.platform == 'darwin':
                filename = hfs_quote(filename)
            if sys.platform == 'win32':
                filename = ntfsdecode(filename)
            else:
                filename = fsdecode(filename)
            if sys.platform == 'darwin':
                filename = decompose(filename)
            res.add(filename)
    return res


def _gitlsdirs(files, prefix_length):
    # Return directories managed by Git
    dirs = set()
    for file in files:
        dir = posixpath.dirname(file)
        while len(dir) > prefix_length:
            dirs.add(dir)
            dir = posixpath.dirname(dir)
    return dirs


def listfiles(dirname=''):
    git_files = gitlsfiles(dirname)
    if not git_files:
        return

    cwd = realpath(dirname or os.curdir)
    prefix_length = len(cwd) + 1

    git_dirs = _gitlsdirs(git_files, prefix_length)

    if sys.version_info >= (2, 6):
        walker = os.walk(cwd, followlinks=True)
    else:
        walker = os.walk(cwd)

    for root, dirs, files in walker:
        dirs[:] = [x for x in dirs if posix(realpath(join(root, x))) in git_dirs]
        for file in files:
            filename = join(root, file)
            if posix(realpath(filename)) in git_files:
                yield filename[prefix_length:]


if __name__ == '__main__':
    if len(sys.argv) > 1:
        dirname = sys.argv[1]
    else:
        dirname = ''
    for filename in listfiles(dirname):
        try:
            print(compose(filename))
        except UnicodeEncodeError:
            print(repr(filename)[1:-1])