blob: 92ea2be91d819c403d2b425d28e15f135b269e47 [file] [log] [blame]
msb@chromium.orge28e4982009-09-25 20:51:45 +00001#!/usr/bin/python
maruel@chromium.orgba551772010-02-03 18:21:42 +00002# Copyright (c) 2010 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
msb@chromium.orge28e4982009-09-25 20:51:45 +00005
6"""Unit tests for gclient_scm.py."""
7
maruel@chromium.orgba551772010-02-03 18:21:42 +00008# Import before super_mox to keep valid references.
9from os import rename
10from shutil import rmtree
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000011from subprocess import Popen, PIPE, STDOUT
msb@chromium.orge28e4982009-09-25 20:51:45 +000012import tempfile
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +000013import __builtin__
msb@chromium.orge28e4982009-09-25 20:51:45 +000014
maruel@chromium.orgba551772010-02-03 18:21:42 +000015# Fixes include path.
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +000016from super_mox import mox, SuperMoxBaseTestBase, SuperMoxTestBase
maruel@chromium.orgba551772010-02-03 18:21:42 +000017
msb@chromium.orge28e4982009-09-25 20:51:45 +000018import gclient_scm
maruel@chromium.org96913eb2010-06-01 16:22:47 +000019
20
21class GCBaseTestCase(SuperMoxTestBase):
22 # Like unittest's assertRaises, but checks for Gclient.Error.
23 def assertRaisesError(self, msg, fn, *args, **kwargs):
24 try:
25 fn(*args, **kwargs)
26 except gclient_scm.gclient_utils.Error, e:
27 self.assertEquals(e.args[0], msg)
28 else:
29 self.fail('%s not raised' % msg)
msb@chromium.orge28e4982009-09-25 20:51:45 +000030
31
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000032class BaseTestCase(GCBaseTestCase):
33 def setUp(self):
34 GCBaseTestCase.setUp(self)
35 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileRead')
36 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileWrite')
37 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'SubprocessCall')
38 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'RemoveDirectory')
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +000039 self._CaptureSVNInfo = gclient_scm.scm.SVN.CaptureInfo
40 self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'Capture')
41 self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'CaptureInfo')
42 self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'CaptureStatus')
43 self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'Run')
44 self.mox.StubOutWithMock(gclient_scm.scm.SVN, 'RunAndGetFileList')
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000045 self._scm_wrapper = gclient_scm.CreateSCM
46
47
48class SVNWrapperTestCase(BaseTestCase):
msb@chromium.orge28e4982009-09-25 20:51:45 +000049 class OptionsObject(object):
50 def __init__(self, test_case, verbose=False, revision=None):
51 self.verbose = verbose
52 self.revision = revision
53 self.manually_grab_svn_rev = True
54 self.deps_os = None
55 self.force = False
davemoore@chromium.org8bf27312010-02-19 17:29:44 +000056 self.reset = False
msb@chromium.orge28e4982009-09-25 20:51:45 +000057 self.nohooks = False
58
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000059 def Options(self, *args, **kwargs):
60 return self.OptionsObject(self, *args, **kwargs)
61
msb@chromium.orge28e4982009-09-25 20:51:45 +000062 def setUp(self):
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000063 BaseTestCase.setUp(self)
msb@chromium.orge28e4982009-09-25 20:51:45 +000064 self.root_dir = self.Dir()
65 self.args = self.Args()
66 self.url = self.Url()
67 self.relpath = 'asf'
68
69 def testDir(self):
70 members = [
tony@chromium.org99828122010-06-04 01:41:02 +000071 'AddAdditionalFlags', 'FullUrlForRelativeUrl', 'RunCommand',
maruel@chromium.org55e724e2010-03-11 19:36:49 +000072 'cleanup', 'diff', 'export', 'pack', 'relpath', 'revert',
maruel@chromium.org9eda4112010-06-11 18:56:10 +000073 'revinfo', 'runhooks', 'status', 'update',
tony@chromium.org4b5b1772010-04-08 01:52:56 +000074 'updatesingle', 'url',
msb@chromium.orge28e4982009-09-25 20:51:45 +000075 ]
76
77 # If you add a member, be sure to add the relevant test!
maruel@chromium.org9eda4112010-06-11 18:56:10 +000078 self.compareMembers(self._scm_wrapper('svn://a'), members)
msb@chromium.orge28e4982009-09-25 20:51:45 +000079
80 def testUnsupportedSCM(self):
maruel@chromium.org9eda4112010-06-11 18:56:10 +000081 args = ['gopher://foo', self.root_dir, self.relpath]
82 exception_msg = 'No SCM found for url gopher://foo'
83 self.assertRaisesError(exception_msg, self._scm_wrapper, *args)
msb@chromium.orge28e4982009-09-25 20:51:45 +000084
msb@chromium.orge6f78352010-01-13 17:05:33 +000085 def testSVNFullUrlForRelativeUrl(self):
86 self.url = 'svn://a/b/c/d'
87
88 self.mox.ReplayAll()
89 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
90 relpath=self.relpath)
91 self.assertEqual(scm.FullUrlForRelativeUrl('/crap'), 'svn://a/b/crap')
92
93 def testGITFullUrlForRelativeUrl(self):
94 self.url = 'git://a/b/c/d'
95
96 self.mox.ReplayAll()
97 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
98 relpath=self.relpath)
99 self.assertEqual(scm.FullUrlForRelativeUrl('/crap'), 'git://a/b/c/crap')
100
msb@chromium.orge28e4982009-09-25 20:51:45 +0000101 def testRunCommandException(self):
102 options = self.Options(verbose=False)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000103 file_path = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
104 gclient_scm.os.path.exists(file_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000105
106 self.mox.ReplayAll()
107 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
108 relpath=self.relpath)
109 exception = "Unsupported argument(s): %s" % ','.join(self.args)
110 self.assertRaisesError(exception, scm.RunCommand,
111 'update', options, self.args)
112
113 def testRunCommandUnknown(self):
114 # TODO(maruel): if ever used.
115 pass
116
117 def testRevertMissing(self):
118 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000119 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
120 gclient_scm.os.path.isdir(base_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000121 # It'll to a checkout instead.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000122 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
123 ).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000124 print("\n_____ %s is missing, synching instead" % self.relpath)
125 # Checkout.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000126 gclient_scm.os.path.exists(base_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000127 files_list = self.mox.CreateMockAnything()
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000128 gclient_scm.scm.SVN.RunAndGetFileList(options,
129 ['checkout', self.url, base_path],
130 self.root_dir, files_list)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000131
132 self.mox.ReplayAll()
133 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
134 relpath=self.relpath)
135 scm.revert(options, self.args, files_list)
136
137 def testRevertNone(self):
138 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000139 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
140 gclient_scm.os.path.isdir(base_path).AndReturn(True)
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000141 gclient_scm.scm.SVN.CaptureStatus(base_path).AndReturn([])
142 gclient_scm.scm.SVN.RunAndGetFileList(options,
143 ['update', '--revision', 'BASE'],
144 base_path, mox.IgnoreArg())
msb@chromium.orge28e4982009-09-25 20:51:45 +0000145
146 self.mox.ReplayAll()
147 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
148 relpath=self.relpath)
149 file_list = []
150 scm.revert(options, self.args, file_list)
151
152 def testRevert2Files(self):
153 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000154 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
155 gclient_scm.os.path.isdir(base_path).AndReturn(True)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000156 items = [
157 ('M ', 'a'),
158 ('A ', 'b'),
159 ]
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000160 file_path1 = gclient_scm.os.path.join(base_path, 'a')
161 file_path2 = gclient_scm.os.path.join(base_path, 'b')
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000162 gclient_scm.scm.SVN.CaptureStatus(base_path).AndReturn(items)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000163 gclient_scm.os.path.exists(file_path1).AndReturn(True)
164 gclient_scm.os.path.isfile(file_path1).AndReturn(True)
165 gclient_scm.os.remove(file_path1)
166 gclient_scm.os.path.exists(file_path2).AndReturn(True)
167 gclient_scm.os.path.isfile(file_path2).AndReturn(True)
168 gclient_scm.os.remove(file_path2)
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000169 gclient_scm.scm.SVN.RunAndGetFileList(options,
170 ['update', '--revision', 'BASE'],
171 base_path, mox.IgnoreArg())
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000172 print(gclient_scm.os.path.join(base_path, 'a'))
173 print(gclient_scm.os.path.join(base_path, 'b'))
msb@chromium.orge28e4982009-09-25 20:51:45 +0000174
175 self.mox.ReplayAll()
176 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
177 relpath=self.relpath)
178 file_list = []
179 scm.revert(options, self.args, file_list)
180
181 def testRevertDirectory(self):
182 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000183 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
184 gclient_scm.os.path.isdir(base_path).AndReturn(True)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000185 items = [
186 ('~ ', 'a'),
187 ]
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000188 gclient_scm.scm.SVN.CaptureStatus(base_path).AndReturn(items)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000189 file_path = gclient_scm.os.path.join(base_path, 'a')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000190 print(file_path)
191 gclient_scm.os.path.exists(file_path).AndReturn(True)
192 gclient_scm.os.path.isfile(file_path).AndReturn(False)
msb@chromium.org32906d12010-01-12 18:22:09 +0000193 gclient_scm.os.path.islink(file_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000194 gclient_scm.os.path.isdir(file_path).AndReturn(True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000195 gclient_scm.gclient_utils.RemoveDirectory(file_path)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000196 file_list1 = []
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000197 gclient_scm.scm.SVN.RunAndGetFileList(options,
198 ['update', '--revision', 'BASE'],
199 base_path, mox.IgnoreArg())
msb@chromium.orge28e4982009-09-25 20:51:45 +0000200
201 self.mox.ReplayAll()
202 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
203 relpath=self.relpath)
204 file_list2 = []
205 scm.revert(options, self.args, file_list2)
206
207 def testStatus(self):
208 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000209 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
210 gclient_scm.os.path.isdir(base_path).AndReturn(True)
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000211 gclient_scm.scm.SVN.RunAndGetFileList(options,
212 ['status'] + self.args,
213 base_path, []).AndReturn(None)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000214
215 self.mox.ReplayAll()
216 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
217 relpath=self.relpath)
218 file_list = []
219 self.assertEqual(scm.status(options, self.args, file_list), None)
220
221
222 # TODO(maruel): TEST REVISIONS!!!
223 # TODO(maruel): TEST RELOCATE!!!
224 def testUpdateCheckout(self):
225 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000226 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
227 file_info = gclient_scm.gclient_utils.PrintableObject()
msb@chromium.orge28e4982009-09-25 20:51:45 +0000228 file_info.root = 'blah'
229 file_info.url = self.url
230 file_info.uuid = 'ABC'
231 file_info.revision = 42
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000232 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
233 ).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000234 # Checkout.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000235 gclient_scm.os.path.exists(base_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000236 files_list = self.mox.CreateMockAnything()
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000237 gclient_scm.scm.SVN.RunAndGetFileList(options,
238 ['checkout', self.url, base_path],
239 self.root_dir, files_list)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000240 self.mox.ReplayAll()
241 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
242 relpath=self.relpath)
243 scm.update(options, (), files_list)
244
245 def testUpdateUpdate(self):
246 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000247 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000248 options.force = True
249 options.nohooks = False
250 file_info = {
251 'Repository Root': 'blah',
252 'URL': self.url,
253 'UUID': 'ABC',
254 'Revision': 42,
255 }
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000256 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
257 ).AndReturn(False)
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000258
259 # Verify no locked files.
260 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
261 ).AndReturn([])
262
msb@chromium.orge28e4982009-09-25 20:51:45 +0000263 # Checkout or update.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000264 gclient_scm.os.path.exists(base_path).AndReturn(True)
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000265 gclient_scm.scm.SVN.CaptureInfo(
266 gclient_scm.os.path.join(base_path, "."), '.'
267 ).AndReturn(file_info)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000268 # Cheat a bit here.
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000269 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000270 additional_args = []
271 if options.manually_grab_svn_rev:
272 additional_args = ['--revision', str(file_info['Revision'])]
tony@chromium.org99828122010-06-04 01:41:02 +0000273 if options.force and gclient_scm.scm.SVN.AssertVersion("1.5")[0]:
274 additional_args.append('--force')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000275 files_list = []
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000276 gclient_scm.scm.SVN.RunAndGetFileList(
277 options,
278 ['update', base_path] + additional_args,
279 self.root_dir, files_list)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000280
281 self.mox.ReplayAll()
282 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
283 relpath=self.relpath)
284 scm.update(options, (), files_list)
285
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000286 def testUpdateSingleCheckout(self):
287 options = self.Options(verbose=True)
288 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
289 file_info = {
290 'URL': self.url,
291 'Revision': 42,
292 }
tony@chromium.org57564662010-04-14 02:35:12 +0000293
294 # Checks to make sure that we support svn co --depth.
295 gclient_scm.scm.SVN.current_version = None
296 gclient_scm.scm.SVN.Capture(['--version']
297 ).AndReturn('svn, version 1.5.1 (r32289)')
298 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.svn')
299 ).AndReturn(False)
300 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, 'DEPS')
301 ).AndReturn(False)
302
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000303 # Verify no locked files.
304 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
305 ).AndReturn([])
306
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000307 # When checking out a single file, we issue an svn checkout and svn update.
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000308 files_list = self.mox.CreateMockAnything()
309 gclient_scm.scm.SVN.Run(
310 ['checkout', '--depth', 'empty', self.url, base_path], self.root_dir)
311 gclient_scm.scm.SVN.RunAndGetFileList(options, ['update', 'DEPS'],
312 gclient_scm.os.path.join(self.root_dir, self.relpath), files_list)
313
314 # Now we fall back on scm.update().
315 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
tony@chromium.org57564662010-04-14 02:35:12 +0000316 ).AndReturn(False)
317 gclient_scm.os.path.exists(base_path).AndReturn(True)
318 gclient_scm.scm.SVN.CaptureInfo(
319 gclient_scm.os.path.join(base_path, "."), '.'
320 ).AndReturn(file_info)
321 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
322 print("\n_____ %s at 42" % self.relpath)
323
324 self.mox.ReplayAll()
325 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
326 relpath=self.relpath)
327 scm.updatesingle(options, ['DEPS'], files_list)
328
329 def testUpdateSingleCheckoutSVN14(self):
330 options = self.Options(verbose=True)
331 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
332 file_info = {
333 'URL': self.url,
334 'Revision': 42,
335 }
336
337 # Checks to make sure that we support svn co --depth.
338 gclient_scm.scm.SVN.current_version = None
339 gclient_scm.scm.SVN.Capture(['--version']
340 ).AndReturn('svn, version 1.4.4 (r25188)')
341 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path)
342 ).AndReturn(True)
343
344 # When checking out a single file with svn 1.4, we use svn export
345 files_list = self.mox.CreateMockAnything()
346 gclient_scm.scm.SVN.Run(
347 ['export', gclient_scm.os.path.join(self.url, 'DEPS'),
348 gclient_scm.os.path.join(base_path, 'DEPS')], self.root_dir)
349
350 self.mox.ReplayAll()
351 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
352 relpath=self.relpath)
353 scm.updatesingle(options, ['DEPS'], files_list)
354
355 def testUpdateSingleCheckoutSVNUpgrade(self):
356 options = self.Options(verbose=True)
357 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
358 file_info = {
359 'URL': self.url,
360 'Revision': 42,
361 }
362
363 # Checks to make sure that we support svn co --depth.
364 gclient_scm.scm.SVN.current_version = None
365 gclient_scm.scm.SVN.Capture(['--version']
366 ).AndReturn('svn, version 1.5.1 (r32289)')
367 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.svn')
368 ).AndReturn(False)
369 # If DEPS already exists, assume we're upgrading from svn1.4, so delete
370 # the old DEPS file.
371 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, 'DEPS')
372 ).AndReturn(True)
373 gclient_scm.os.remove(gclient_scm.os.path.join(base_path, 'DEPS'))
374
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000375 # Verify no locked files.
376 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
377 ).AndReturn([])
378
tony@chromium.org57564662010-04-14 02:35:12 +0000379 # When checking out a single file, we issue an svn checkout and svn update.
380 files_list = self.mox.CreateMockAnything()
381 gclient_scm.scm.SVN.Run(
382 ['checkout', '--depth', 'empty', self.url, base_path], self.root_dir)
383 gclient_scm.scm.SVN.RunAndGetFileList(options, ['update', 'DEPS'],
384 gclient_scm.os.path.join(self.root_dir, self.relpath), files_list)
385
386 # Now we fall back on scm.update().
387 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
388 ).AndReturn(False)
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000389 gclient_scm.os.path.exists(base_path).AndReturn(True)
390 gclient_scm.scm.SVN.CaptureInfo(
391 gclient_scm.os.path.join(base_path, "."), '.'
392 ).AndReturn(file_info)
393 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
394 print("\n_____ %s at 42" % self.relpath)
395
396 self.mox.ReplayAll()
397 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
398 relpath=self.relpath)
399 scm.updatesingle(options, ['DEPS'], files_list)
400
401 def testUpdateSingleUpdate(self):
402 options = self.Options(verbose=True)
403 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
404 file_info = {
405 'URL': self.url,
406 'Revision': 42,
407 }
tony@chromium.org57564662010-04-14 02:35:12 +0000408 # Checks to make sure that we support svn co --depth.
409 gclient_scm.scm.SVN.current_version = None
410 gclient_scm.scm.SVN.Capture(['--version']
411 ).AndReturn('svn, version 1.5.1 (r32289)')
412 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.svn')
413 ).AndReturn(True)
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000414
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000415 # Verify no locked files.
416 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
417 ).AndReturn([])
418
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000419 # Now we fall back on scm.update().
420 files_list = self.mox.CreateMockAnything()
421 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
422 ).AndReturn(False)
423 gclient_scm.os.path.exists(base_path).AndReturn(True)
424 gclient_scm.scm.SVN.CaptureInfo(
425 gclient_scm.os.path.join(base_path, "."), '.'
426 ).AndReturn(file_info)
427 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
428 print("\n_____ %s at 42" % self.relpath)
429
430 self.mox.ReplayAll()
431 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
432 relpath=self.relpath)
433 scm.updatesingle(options, ['DEPS'], files_list)
434
msb@chromium.orge28e4982009-09-25 20:51:45 +0000435 def testUpdateGit(self):
436 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000437 file_path = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
438 gclient_scm.os.path.exists(file_path).AndReturn(True)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000439 print("________ found .git directory; skipping %s" % self.relpath)
440
441 self.mox.ReplayAll()
442 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
443 relpath=self.relpath)
444 file_list = []
445 scm.update(options, self.args, file_list)
446
msb@chromium.orge28e4982009-09-25 20:51:45 +0000447
msb@chromium.org5bde4852009-12-14 16:47:12 +0000448class GitWrapperTestCase(BaseTestCase):
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000449 """This class doesn't use pymox."""
msb@chromium.orge28e4982009-09-25 20:51:45 +0000450 class OptionsObject(object):
451 def __init__(self, test_case, verbose=False, revision=None):
452 self.verbose = verbose
453 self.revision = revision
454 self.manually_grab_svn_rev = True
455 self.deps_os = None
456 self.force = False
davemoore@chromium.org8bf27312010-02-19 17:29:44 +0000457 self.reset = False
msb@chromium.orge28e4982009-09-25 20:51:45 +0000458 self.nohooks = False
459
460 sample_git_import = """blob
461mark :1
462data 6
463Hello
464
465blob
466mark :2
467data 4
468Bye
469
470reset refs/heads/master
471commit refs/heads/master
472mark :3
473author Bob <bob@example.com> 1253744361 -0700
474committer Bob <bob@example.com> 1253744361 -0700
475data 8
476A and B
477M 100644 :1 a
478M 100644 :2 b
479
480blob
481mark :4
482data 10
483Hello
484You
485
486blob
487mark :5
488data 8
489Bye
490You
491
492commit refs/heads/origin
493mark :6
494author Alice <alice@example.com> 1253744424 -0700
495committer Alice <alice@example.com> 1253744424 -0700
496data 13
497Personalized
498from :3
499M 100644 :4 a
500M 100644 :5 b
501
502reset refs/heads/master
503from :3
504"""
msb@chromium.orge28e4982009-09-25 20:51:45 +0000505 def Options(self, *args, **kwargs):
506 return self.OptionsObject(self, *args, **kwargs)
507
508 def CreateGitRepo(self, git_import, path):
maruel@chromium.orgd5800f12009-11-12 20:03:43 +0000509 """Do it for real."""
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000510 try:
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000511 Popen(['git', 'init'], stdout=PIPE, stderr=STDOUT,
512 cwd=path).communicate()
513 except OSError:
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000514 # git is not available, skip this test.
515 return False
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000516 Popen(['git', 'fast-import'], stdin=PIPE, stdout=PIPE, stderr=STDOUT,
517 cwd=path).communicate(input=git_import)
518 Popen(['git', 'checkout'], stdout=PIPE, stderr=STDOUT,
519 cwd=path).communicate()
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000520 Popen(['git', 'remote', 'add', '-f', 'origin', '.'], stdout=PIPE,
521 stderr=STDOUT, cwd=path).communicate()
522 Popen(['git', 'checkout', '-b', 'new', 'origin/master'], stdout=PIPE,
523 stderr=STDOUT, cwd=path).communicate()
524 Popen(['git', 'push', 'origin', 'origin/origin:origin/master'], stdout=PIPE,
525 stderr=STDOUT, cwd=path).communicate()
526 Popen(['git', 'config', '--unset', 'remote.origin.fetch'], stdout=PIPE,
527 stderr=STDOUT, cwd=path).communicate()
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000528 return True
msb@chromium.orge28e4982009-09-25 20:51:45 +0000529
msb@chromium.orge28e4982009-09-25 20:51:45 +0000530 def setUp(self):
msb@chromium.orge28e4982009-09-25 20:51:45 +0000531 self.args = self.Args()
532 self.url = 'git://foo'
533 self.root_dir = tempfile.mkdtemp()
534 self.relpath = '.'
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000535 self.base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000536 self.enabled = self.CreateGitRepo(self.sample_git_import, self.base_path)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000537 SuperMoxBaseTestBase.setUp(self)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000538
539 def tearDown(self):
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000540 SuperMoxBaseTestBase.tearDown(self)
maruel@chromium.orgba551772010-02-03 18:21:42 +0000541 rmtree(self.root_dir)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000542
543 def testDir(self):
544 members = [
maruel@chromium.org55e724e2010-03-11 19:36:49 +0000545 'FullUrlForRelativeUrl', 'RunCommand',
msb@chromium.orge6f78352010-01-13 17:05:33 +0000546 'cleanup', 'diff', 'export', 'pack', 'relpath', 'revert',
maruel@chromium.org9eda4112010-06-11 18:56:10 +0000547 'revinfo', 'runhooks', 'status', 'update', 'url',
msb@chromium.orge28e4982009-09-25 20:51:45 +0000548 ]
549
550 # If you add a member, be sure to add the relevant test!
551 self.compareMembers(gclient_scm.CreateSCM(url=self.url), members)
552
553 def testRevertMissing(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000554 if not self.enabled:
555 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000556 options = self.Options()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000557 file_path = gclient_scm.os.path.join(self.base_path, 'a')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000558 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
559 relpath=self.relpath)
560 file_list = []
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000561 scm.update(options, None, file_list)
562 gclient_scm.os.remove(file_path)
563 file_list = []
msb@chromium.orge28e4982009-09-25 20:51:45 +0000564 scm.revert(options, self.args, file_list)
565 self.assertEquals(file_list, [file_path])
566 file_list = []
567 scm.diff(options, self.args, file_list)
568 self.assertEquals(file_list, [])
569
570 def testRevertNone(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000571 if not self.enabled:
572 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000573 options = self.Options()
574 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
575 relpath=self.relpath)
576 file_list = []
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000577 scm.update(options, None, file_list)
578 file_list = []
msb@chromium.orge28e4982009-09-25 20:51:45 +0000579 scm.revert(options, self.args, file_list)
580 self.assertEquals(file_list, [])
msb@chromium.org0f282062009-11-06 20:14:02 +0000581 self.assertEquals(scm.revinfo(options, self.args, None),
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000582 'a7142dc9f0009350b96a11f372b6ea658592aa95')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000583
584
585 def testRevertModified(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000586 if not self.enabled:
587 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000588 options = self.Options()
msb@chromium.orge28e4982009-09-25 20:51:45 +0000589 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
590 relpath=self.relpath)
591 file_list = []
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000592 scm.update(options, None, file_list)
593 file_path = gclient_scm.os.path.join(self.base_path, 'a')
594 open(file_path, 'a').writelines('touched\n')
595 file_list = []
msb@chromium.orge28e4982009-09-25 20:51:45 +0000596 scm.revert(options, self.args, file_list)
597 self.assertEquals(file_list, [file_path])
598 file_list = []
599 scm.diff(options, self.args, file_list)
600 self.assertEquals(file_list, [])
msb@chromium.org0f282062009-11-06 20:14:02 +0000601 self.assertEquals(scm.revinfo(options, self.args, None),
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000602 'a7142dc9f0009350b96a11f372b6ea658592aa95')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000603
604 def testRevertNew(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000605 if not self.enabled:
606 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000607 options = self.Options()
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000608 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
609 relpath=self.relpath)
610 file_list = []
611 scm.update(options, None, file_list)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000612 file_path = gclient_scm.os.path.join(self.base_path, 'c')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000613 f = open(file_path, 'w')
614 f.writelines('new\n')
615 f.close()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000616 Popen(['git', 'add', 'c'], stdout=PIPE,
617 stderr=STDOUT, cwd=self.base_path).communicate()
msb@chromium.orge28e4982009-09-25 20:51:45 +0000618 file_list = []
619 scm.revert(options, self.args, file_list)
620 self.assertEquals(file_list, [file_path])
621 file_list = []
622 scm.diff(options, self.args, file_list)
623 self.assertEquals(file_list, [])
msb@chromium.org0f282062009-11-06 20:14:02 +0000624 self.assertEquals(scm.revinfo(options, self.args, None),
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000625 'a7142dc9f0009350b96a11f372b6ea658592aa95')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000626
627 def testStatusNew(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000628 if not self.enabled:
629 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000630 options = self.Options()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000631 file_path = gclient_scm.os.path.join(self.base_path, 'a')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000632 open(file_path, 'a').writelines('touched\n')
633 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
634 relpath=self.relpath)
635 file_list = []
636 scm.status(options, self.args, file_list)
637 self.assertEquals(file_list, [file_path])
638
639 def testStatus2New(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000640 if not self.enabled:
641 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000642 options = self.Options()
643 expected_file_list = []
644 for f in ['a', 'b']:
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000645 file_path = gclient_scm.os.path.join(self.base_path, f)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000646 open(file_path, 'a').writelines('touched\n')
647 expected_file_list.extend([file_path])
648 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
649 relpath=self.relpath)
650 file_list = []
651 scm.status(options, self.args, file_list)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000652 expected_file_list = [gclient_scm.os.path.join(self.base_path, x)
653 for x in ['a', 'b']]
msb@chromium.orge28e4982009-09-25 20:51:45 +0000654 self.assertEquals(sorted(file_list), expected_file_list)
655
656 def testUpdateCheckout(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000657 if not self.enabled:
658 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000659 options = self.Options(verbose=True)
660 root_dir = tempfile.mkdtemp()
661 relpath = 'foo'
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000662 base_path = gclient_scm.os.path.join(root_dir, relpath)
663 url = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000664 try:
665 scm = gclient_scm.CreateSCM(url=url, root_dir=root_dir,
666 relpath=relpath)
667 file_list = []
668 scm.update(options, (), file_list)
669 self.assertEquals(len(file_list), 2)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000670 self.assert_(gclient_scm.os.path.isfile(
671 gclient_scm.os.path.join(base_path, 'a')))
msb@chromium.org0f282062009-11-06 20:14:02 +0000672 self.assertEquals(scm.revinfo(options, (), None),
msb@chromium.orge28e4982009-09-25 20:51:45 +0000673 '069c602044c5388d2d15c3f875b057c852003458')
674 finally:
maruel@chromium.orgba551772010-02-03 18:21:42 +0000675 rmtree(root_dir)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000676
677 def testUpdateUpdate(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000678 if not self.enabled:
679 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000680 options = self.Options()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000681 expected_file_list = [gclient_scm.os.path.join(self.base_path, x)
682 for x in ['a', 'b']]
msb@chromium.orge28e4982009-09-25 20:51:45 +0000683 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
684 relpath=self.relpath)
685 file_list = []
686 scm.update(options, (), file_list)
msb@chromium.org0f282062009-11-06 20:14:02 +0000687 self.assertEquals(file_list, expected_file_list)
688 self.assertEquals(scm.revinfo(options, (), None),
msb@chromium.orge28e4982009-09-25 20:51:45 +0000689 'a7142dc9f0009350b96a11f372b6ea658592aa95')
690
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000691 def testUpdateUnstagedConflict(self):
692 if not self.enabled:
693 return
694 options = self.Options()
695 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
696 relpath=self.relpath)
697 file_path = gclient_scm.os.path.join(self.base_path, 'b')
698 f = open(file_path, 'w').writelines('conflict\n')
699 exception = (
700 "error: Your local changes to 'b' would be overwritten by merge. "
701 "Aborting.\n"
702 "Please, commit your changes or stash them before you can merge.\n")
703 self.assertRaisesError(exception, scm.update, options, (), [])
704
msb@chromium.org5bde4852009-12-14 16:47:12 +0000705 def testUpdateConflict(self):
706 if not self.enabled:
707 return
708 options = self.Options()
709 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
710 relpath=self.relpath)
711 file_path = gclient_scm.os.path.join(self.base_path, 'b')
712 f = open(file_path, 'w').writelines('conflict\n')
713 scm._Run(['commit', '-am', 'test'])
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000714 self.mox.StubOutWithMock(__builtin__, 'raw_input')
715 __builtin__.raw_input.__call__(mox.StrContains('Cannot fast-forward merge, '
716 'attempt to rebase? (y)es / '
717 '(q)uit / (s)kip : ')
718 ).AndReturn('y')
719 self.mox.ReplayAll()
msb@chromium.org5bde4852009-12-14 16:47:12 +0000720 exception = \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000721 'Conflict while rebasing this branch.\n' \
msb@chromium.org5bde4852009-12-14 16:47:12 +0000722 'Fix the conflict and run gclient again.\n' \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000723 "See 'man git-rebase' for details.\n"
msb@chromium.org5bde4852009-12-14 16:47:12 +0000724 self.assertRaisesError(exception, scm.update, options, (), [])
725 exception = \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000726 '\n____ . at refs/heads/master\n' \
msb@chromium.org786fb682010-06-02 15:16:23 +0000727 '\tYou have unstaged changes.\n' \
728 '\tPlease commit, stash, or reset.\n'
msb@chromium.org5bde4852009-12-14 16:47:12 +0000729 self.assertRaisesError(exception, scm.update, options, (), [])
730
msb@chromium.orge4af1ab2010-01-13 21:26:09 +0000731 def testUpdateNotGit(self):
732 if not self.enabled:
733 return
734 options = self.Options()
735 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
736 relpath=self.relpath)
737 git_path = gclient_scm.os.path.join(self.base_path, '.git')
maruel@chromium.orgba551772010-02-03 18:21:42 +0000738 rename(git_path, git_path + 'foo')
msb@chromium.orge4af1ab2010-01-13 21:26:09 +0000739 exception = \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000740 '\n____ . at refs/heads/master\n' \
msb@chromium.orge4af1ab2010-01-13 21:26:09 +0000741 '\tPath is not a git repo. No .git dir.\n' \
742 '\tTo resolve:\n' \
743 '\t\trm -rf .\n' \
744 '\tAnd run gclient sync again\n'
745 self.assertRaisesError(exception, scm.update, options, (), [])
746
msb@chromium.org0f282062009-11-06 20:14:02 +0000747 def testRevinfo(self):
748 if not self.enabled:
749 return
750 options = self.Options()
751 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
752 relpath=self.relpath)
753 rev_info = scm.revinfo(options, (), None)
754 self.assertEquals(rev_info, '069c602044c5388d2d15c3f875b057c852003458')
755
msb@chromium.orge28e4982009-09-25 20:51:45 +0000756
msb@chromium.orge28e4982009-09-25 20:51:45 +0000757if __name__ == '__main__':
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000758 import unittest
msb@chromium.orge28e4982009-09-25 20:51:45 +0000759 unittest.main()
760
761# vim: ts=2:sw=2:tw=80:et: