Repository navigation
Expand file tree
/
Copy pathgit.py
More file actions
127 lines (97 loc) · 4.3 KB
/
Copy pathgit.py
File metadata and controls
127 lines (97 loc) · 4.3 KB
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
import datetime
import logging
import os
from subprocess import Popen, PIPE
from django.conf import settings
from .exceptions import CommitLogError
logger = logging.getLogger(__name__)
def execute_command(cmd, cwd):
p = Popen(cmd, stdout=PIPE, stderr=PIPE, cwd=cwd)
stdout, stderr = p.communicate()
stdout = stdout.decode('utf8') if stdout is not None else stdout
stderr = stderr.decode('utf8') if stderr is not None else stderr
return (p, stdout, stderr)
def updaterepo(project, update=True):
if os.path.exists(project.working_copy):
if not update:
return
p, _, stderr = execute_command(['git', 'pull'], cwd=project.working_copy)
if p.returncode != 0:
raise CommitLogError("git pull returned %s: %s" % (p.returncode,
stderr))
else:
return [{'error': False}]
else:
cmd = ['git', 'clone', project.repo_path, project.repo_name]
p, stdout, stderr = execute_command(cmd, settings.REPOSITORY_BASE_PATH)
logger.debug('Cloning Git repo {0} for project {1}'.format(
project.repo_path, project))
if p.returncode != 0:
raise CommitLogError("%s returned %s: %s" % (
" ".join(cmd), p.returncode, stderr))
else:
return [{'error': False}]
def get_commit_date(project, commit_id):
"""Author date of `commit_id` as a naive UTC datetime, or None."""
updaterepo(project, update=False)
fmt = '%ct' if getattr(settings, 'GIT_USE_COMMIT_DATE', False) else '%at'
cmd = ['git', 'log', '-1', '--format=' + fmt, commit_id]
p, stdout, stderr = execute_command(cmd, project.working_copy)
if p.returncode != 0 or not stdout.strip():
logger.warning("%s returned %s: %s", " ".join(cmd), p.returncode, stderr)
return None
return datetime.datetime.utcfromtimestamp(int(stdout.strip()))
class Git:
"""Git backend with the same interface as commits.mercurial.Mercurial."""
def __init__(self, project):
self.project = project
def update_repo(self, update=True):
return updaterepo(self.project, update=update)
def get_logs(self, endrev, startrev):
return getlogs(endrev, startrev)
def get_commit_date(self, commit_id):
return get_commit_date(self.project, commit_id)
def getlogs(endrev, startrev):
updaterepo(endrev.branch.project, update=False)
# NULL separated values delimited by 0x1e record separators
# See PRETTY FORMATS in git-log(1):
if hasattr(settings, 'GIT_USE_COMMIT_DATE') and settings.GIT_USE_COMMIT_DATE:
logfmt = '--format=format:%h%x00%H%x00%ct%x00%an%x00%ae%x00%s%x00%b%x1e'
else:
logfmt = '--format=format:%h%x00%H%x00%at%x00%an%x00%ae%x00%s%x00%b%x1e'
max_log_entries = getattr(settings, 'GIT_MAX_LOG_ENTRIES', 30)
cmd = ["git", "log", logfmt]
if endrev.commitid != startrev.commitid:
cmd.append("-n%d" % max_log_entries)
cmd.append("%s...%s" % (startrev.commitid, endrev.commitid))
else:
cmd.append("-1") # Only return one commit
cmd.append(endrev.commitid)
working_copy = endrev.branch.project.working_copy
p, stdout, stderr = execute_command(cmd, working_copy)
if p.returncode != 0:
raise CommitLogError("'%s' in '%s' returned %s: %s" % (
" ".join(cmd), working_copy, p.returncode, stderr))
logs = []
for log in filter(None, stdout.split('\x1e')):
(short_commit_id, commit_id, date_t, author_name, author_email,
subject, body) = map(lambda s: s.strip(), log.split('\x00', 7))
cmd = ["git", "tag", "--points-at", commit_id]
try:
p, stdout, stderr = execute_command(cmd, working_copy)
except Exception:
logger.debug('Failed to get tag', exc_info=True)
tag = stdout.strip() if p.returncode == 0 else ""
date = datetime.datetime.utcfromtimestamp(
int(date_t)).strftime("%Y-%m-%d %H:%M:%S")
logs.append({
'date': date,
'message': subject,
'commitid': commit_id,
'author': author_name,
'author_email': author_email,
'body': body,
'short_commit_id': short_commit_id,
'tag': tag
})
return logs