blob: b6a4a343e94663e0d892d24be641a099375a8d00 [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
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070020from trace import REPO_TRACE, IsTrace, Trace
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070021
22GIT = 'git'
23MIN_GIT_VERSION = (1, 5, 4)
24GIT_DIR = 'GIT_DIR'
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070025
26LAST_GITDIR = None
27LAST_CWD = None
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070028
29
30class _GitCall(object):
31 def version(self):
32 p = GitCommand(None, ['--version'], capture_stdout=True)
33 if p.Wait() == 0:
34 return p.stdout
35 return None
36
37 def __getattr__(self, name):
38 name = name.replace('_','-')
39 def fun(*cmdv):
40 command = [name]
41 command.extend(cmdv)
42 return GitCommand(None, command).Wait() == 0
43 return fun
44git = _GitCall()
45
46class GitCommand(object):
47 def __init__(self,
48 project,
49 cmdv,
50 bare = False,
51 provide_stdin = False,
52 capture_stdout = False,
53 capture_stderr = False,
54 disable_editor = False,
55 cwd = None,
56 gitdir = None):
57 env = dict(os.environ)
58
59 for e in [REPO_TRACE,
60 GIT_DIR,
61 'GIT_ALTERNATE_OBJECT_DIRECTORIES',
62 'GIT_OBJECT_DIRECTORY',
63 'GIT_WORK_TREE',
64 'GIT_GRAFT_FILE',
65 'GIT_INDEX_FILE']:
66 if e in env:
67 del env[e]
68
69 if disable_editor:
70 env['GIT_EDITOR'] = ':'
71
72 if project:
73 if not cwd:
74 cwd = project.worktree
75 if not gitdir:
76 gitdir = project.gitdir
77
78 command = [GIT]
79 if bare:
80 if gitdir:
81 env[GIT_DIR] = gitdir
82 cwd = None
83 command.extend(cmdv)
84
85 if provide_stdin:
86 stdin = subprocess.PIPE
87 else:
88 stdin = None
89
90 if capture_stdout:
91 stdout = subprocess.PIPE
92 else:
93 stdout = None
94
95 if capture_stderr:
96 stderr = subprocess.PIPE
97 else:
98 stderr = None
99
Shawn O. Pearcead3193a2009-04-18 09:54:51 -0700100 if IsTrace():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700101 global LAST_CWD
102 global LAST_GITDIR
103
104 dbg = ''
105
106 if cwd and LAST_CWD != cwd:
107 if LAST_GITDIR or LAST_CWD:
108 dbg += '\n'
109 dbg += ': cd %s\n' % cwd
110 LAST_CWD = cwd
111
112 if GIT_DIR in env and LAST_GITDIR != env[GIT_DIR]:
113 if LAST_GITDIR or LAST_CWD:
114 dbg += '\n'
115 dbg += ': export GIT_DIR=%s\n' % env[GIT_DIR]
116 LAST_GITDIR = env[GIT_DIR]
117
118 dbg += ': '
119 dbg += ' '.join(command)
120 if stdin == subprocess.PIPE:
121 dbg += ' 0<|'
122 if stdout == subprocess.PIPE:
123 dbg += ' 1>|'
124 if stderr == subprocess.PIPE:
125 dbg += ' 2>|'
Shawn O. Pearcead3193a2009-04-18 09:54:51 -0700126 Trace('%s', dbg)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700127
128 try:
129 p = subprocess.Popen(command,
130 cwd = cwd,
131 env = env,
132 stdin = stdin,
133 stdout = stdout,
134 stderr = stderr)
135 except Exception, e:
136 raise GitError('%s: %s' % (command[1], e))
137
138 self.process = p
139 self.stdin = p.stdin
140
141 def Wait(self):
142 p = self.process
143
144 if p.stdin:
145 p.stdin.close()
146 self.stdin = None
147
148 if p.stdout:
149 self.stdout = p.stdout.read()
150 p.stdout.close()
151 else:
152 p.stdout = None
153
154 if p.stderr:
155 self.stderr = p.stderr.read()
156 p.stderr.close()
157 else:
158 p.stderr = None
159
160 return self.process.wait()