forked from ligovirgo/dqsegdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vcs.py
163 lines (143 loc) · 5.32 KB
/
vcs.py
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# -*- coding: utf-8 -*-
"""Git version generator
"""
__author__ = 'Duncan Macleod <duncan.macleod@ligo.org>'
__credits__ = 'Adam Mercer <adam.mercer@ligo.org>'
import os
import subprocess
import time
class GitStatus(object):
"""Git repository version information
"""
def __init__(self):
self._bin = self._find_git()
self.id = None
self.date = None
self.branch = None
self.tag = None
self.author = None
self.committer = None
self.status = None
# ------------------------------------------------------------------------
# Core methods
@staticmethod
def _find_git():
"""Determine the full path of the git binary on this
host
"""
for path in os.environ['PATH'].split(os.pathsep):
gitbin = os.path.join(path, 'git')
if os.path.isfile(gitbin) and os.access(gitbin, os.X_OK):
return gitbin
raise ValueError("Git binary not found on this host")
def git(self, *args):
"""Executable a command with arguments in a sub-process
"""
cmdargs = [self._bin] + list(args)
p = subprocess.Popen(cmdargs,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=isinstance(args, basestring))
out, err = p.communicate()
if p.returncode != 0:
raise subprocess.CalledProcessError(p.returncode,
' '.join(cmdargs))
return out.strip()
# ------------------------------------------------------------------------
# Git communication methods
def get_commit_info(self):
"""Determine basic info about the latest commit
"""
a, b, c, d, e, f = self.git(
'log', '-1', '--pretty=format:%H,%ct,%an,%ae,%cn,%ce').split(',')
self.id = a
self.udate = b
author = c
author_email = d
committer = e
committer_email = f
self.date = time.strftime('%Y-%m-%d %H:%M:%S +0000',
time.gmtime(float(self.udate)))
self.author = '%s <%s>' % (author, author_email)
self.committer = '%s <%s>' % (committer, committer_email)
def get_branch(self):
branch = self.git('rev-parse', '--symbolic-full-name', 'HEAD')
if branch == 'HEAD':
self.branch = None
else:
self.branch = os.path.basename(branch)
return self.branch
def get_status(self):
"""Determine modification status of working tree
"""
try:
self.git('diff-files', '--quiet')
except subprocess.CalledProcessError:
self.status = 'UNCLEAN: Modified working tree'
else:
try:
self.git('diff-index', '--cache', '--quiet', 'HEAD')
except subprocess.CalledProcessError:
self.status = 'UNCLEAN: Modified working tree'
else:
self.status = 'CLEAN: All modifications committed'
return self.status
def get_tag(self):
"""Determine name of the current tag
"""
if not self.id:
self.get_commit_info()
try:
self.tag = self.git('describe', '--exact-match', '--tags',
self.id)
except subprocess.CalledProcessError:
self.tag = None
return self.tag
# ------------------------------------------------------------------------
# Write
def write(self, fobj, pname, pauthor=None,
pauthoremail=None):
"""Write the contents of this `GitStatus` to a version.py format
file object
"""
# write file header
fobj.write("# -*- coding: utf-8 -*-\n")
if pauthor:
fobj.write("# Copyright (C) %s (2013)\n\n" % pauthor)
fobj.write("\"\"\"Versioning record for %s\n\"\"\"\n\n"
% pname)
# write standard pythonic metadata
if pauthor and pauthoremail:
pauthor = '%s <%s>' % (pauthor, pauthoremail)
if pauthor:
fobj.write("__author__ = '%s'\n" % pauthor)
fobj.write("__version__ = '%s'\n"
"__date__ = '%s'\n\n" % (self.version, self.date))
# write git information
fobj.write("version = '%s'\n" % self.version)
for attr in ['id', 'branch', 'tag', 'author', 'committer', 'status']:
val = getattr(self, attr)
if val:
fobj.write("git_%s = '%s'\n" % (attr, val))
else:
fobj.write("git_%s = None\n" % attr)
def run(self, outputfile, pname, pauthor=None, pauthoremail=None):
"""Process the version information into a new file
Parameters
----------
outputfile : `str`
path to output python file in which to write version info
Returns
-------
info : `str`
returns a string dump of the contents of the outputfile
"""
self.get_commit_info()
self.get_branch()
self.get_tag()
self.get_status()
self.version = self.tag or self.id[:6]
with open(outputfile, 'w') as fobj:
self.write(fobj, pname, pauthor, pauthoremail)
with open(outputfile, 'r') as fobj:
return fobj.read()