blob: a3bd9192e7f1cd6883caa5e710c0ddcf2e1e2d70 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import os
17import sys
18import subprocess
19from error import GitError
20
21GIT = 'git'
22MIN_GIT_VERSION = (1, 5, 4)
23GIT_DIR = 'GIT_DIR'
24REPO_TRACE = 'REPO_TRACE'
25
26LAST_GITDIR = None
27LAST_CWD = None
28try:
29 TRACE = os.environ[REPO_TRACE] == '1'
30except KeyError:
31 TRACE = False
32
33
34class _GitCall(object):
35 def version(self):
36 p = GitCommand(None, ['--version'], capture_stdout=True)
37 if p.Wait() == 0:
38 return p.stdout
39 return None
40
41 def __getattr__(self, name):
42 name = name.replace('_','-')
43 def fun(*cmdv):
44 command = [name]
45 command.extend(cmdv)
46 return GitCommand(None, command).Wait() == 0
47 return fun
48git = _GitCall()
49
50class GitCommand(object):
51 def __init__(self,
52 project,
53 cmdv,
54 bare = False,
55 provide_stdin = False,
56 capture_stdout = False,
57 capture_stderr = False,
58 disable_editor = False,
59 cwd = None,
60 gitdir = None):
61 env = dict(os.environ)
62
63 for e in [REPO_TRACE,
64 GIT_DIR,
65 'GIT_ALTERNATE_OBJECT_DIRECTORIES',
66 'GIT_OBJECT_DIRECTORY',
67 'GIT_WORK_TREE',
68 'GIT_GRAFT_FILE',
69 'GIT_INDEX_FILE']:
70 if e in env:
71 del env[e]
72
73 if disable_editor:
74 env['GIT_EDITOR'] = ':'
75
76 if project:
77 if not cwd:
78 cwd = project.worktree
79 if not gitdir:
80 gitdir = project.gitdir
81
82 command = [GIT]
83 if bare:
84 if gitdir:
85 env[GIT_DIR] = gitdir
86 cwd = None
87 command.extend(cmdv)
88
89 if provide_stdin:
90 stdin = subprocess.PIPE
91 else:
92 stdin = None
93
94 if capture_stdout:
95 stdout = subprocess.PIPE
96 else:
97 stdout = None
98
99 if capture_stderr:
100 stderr = subprocess.PIPE
101 else:
102 stderr = None
103
104 if TRACE:
105 global LAST_CWD
106 global LAST_GITDIR
107
108 dbg = ''
109
110 if cwd and LAST_CWD != cwd:
111 if LAST_GITDIR or LAST_CWD:
112 dbg += '\n'
113 dbg += ': cd %s\n' % cwd
114 LAST_CWD = cwd
115
116 if GIT_DIR in env and LAST_GITDIR != env[GIT_DIR]:
117 if LAST_GITDIR or LAST_CWD:
118 dbg += '\n'
119 dbg += ': export GIT_DIR=%s\n' % env[GIT_DIR]
120 LAST_GITDIR = env[GIT_DIR]
121
122 dbg += ': '
123 dbg += ' '.join(command)
124 if stdin == subprocess.PIPE:
125 dbg += ' 0<|'
126 if stdout == subprocess.PIPE:
127 dbg += ' 1>|'
128 if stderr == subprocess.PIPE:
129 dbg += ' 2>|'
130 print >>sys.stderr, dbg
131
132 try:
133 p = subprocess.Popen(command,
134 cwd = cwd,
135 env = env,
136 stdin = stdin,
137 stdout = stdout,
138 stderr = stderr)
139 except Exception, e:
140 raise GitError('%s: %s' % (command[1], e))
141
142 self.process = p
143 self.stdin = p.stdin
144
145 def Wait(self):
146 p = self.process
147
148 if p.stdin:
149 p.stdin.close()
150 self.stdin = None
151
152 if p.stdout:
153 self.stdout = p.stdout.read()
154 p.stdout.close()
155 else:
156 p.stdout = None
157
158 if p.stderr:
159 self.stderr = p.stderr.read()
160 p.stderr.close()
161 else:
162 p.stderr = None
163
164 return self.process.wait()