blob: b8399df2ef407f4895993b3793a8128059c1e304 [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)
maruel@chromium.org17d01792010-09-01 18:07:10 +000035 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'CheckCallAndFilter')
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000036 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileRead')
37 self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileWrite')
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000038 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
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +000046 gclient_scm.sys.stdout.flush = lambda: None
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000047
48
49class SVNWrapperTestCase(BaseTestCase):
msb@chromium.orge28e4982009-09-25 20:51:45 +000050 class OptionsObject(object):
51 def __init__(self, test_case, verbose=False, revision=None):
52 self.verbose = verbose
53 self.revision = revision
54 self.manually_grab_svn_rev = True
55 self.deps_os = None
56 self.force = False
davemoore@chromium.org8bf27312010-02-19 17:29:44 +000057 self.reset = False
msb@chromium.orge28e4982009-09-25 20:51:45 +000058 self.nohooks = False
59
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000060 def Options(self, *args, **kwargs):
61 return self.OptionsObject(self, *args, **kwargs)
62
msb@chromium.orge28e4982009-09-25 20:51:45 +000063 def setUp(self):
maruel@chromium.org8ef5f542009-11-12 02:05:02 +000064 BaseTestCase.setUp(self)
msb@chromium.orge28e4982009-09-25 20:51:45 +000065 self.root_dir = self.Dir()
66 self.args = self.Args()
67 self.url = self.Url()
68 self.relpath = 'asf'
69
70 def testDir(self):
71 members = [
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +000072 'FullUrlForRelativeUrl', 'RunCommand',
maruel@chromium.org55e724e2010-03-11 19:36:49 +000073 'cleanup', 'diff', 'export', 'pack', 'relpath', 'revert',
maruel@chromium.org9eda4112010-06-11 18:56:10 +000074 'revinfo', 'runhooks', 'status', 'update',
tony@chromium.org4b5b1772010-04-08 01:52:56 +000075 'updatesingle', 'url',
msb@chromium.orge28e4982009-09-25 20:51:45 +000076 ]
77
78 # If you add a member, be sure to add the relevant test!
maruel@chromium.org9eda4112010-06-11 18:56:10 +000079 self.compareMembers(self._scm_wrapper('svn://a'), members)
msb@chromium.orge28e4982009-09-25 20:51:45 +000080
81 def testUnsupportedSCM(self):
maruel@chromium.org9eda4112010-06-11 18:56:10 +000082 args = ['gopher://foo', self.root_dir, self.relpath]
83 exception_msg = 'No SCM found for url gopher://foo'
84 self.assertRaisesError(exception_msg, self._scm_wrapper, *args)
msb@chromium.orge28e4982009-09-25 20:51:45 +000085
msb@chromium.orge6f78352010-01-13 17:05:33 +000086 def testSVNFullUrlForRelativeUrl(self):
87 self.url = 'svn://a/b/c/d'
88
89 self.mox.ReplayAll()
90 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
91 relpath=self.relpath)
92 self.assertEqual(scm.FullUrlForRelativeUrl('/crap'), 'svn://a/b/crap')
93
94 def testGITFullUrlForRelativeUrl(self):
95 self.url = 'git://a/b/c/d'
96
97 self.mox.ReplayAll()
98 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
99 relpath=self.relpath)
100 self.assertEqual(scm.FullUrlForRelativeUrl('/crap'), 'git://a/b/c/crap')
101
msb@chromium.orge28e4982009-09-25 20:51:45 +0000102 def testRunCommandException(self):
103 options = self.Options(verbose=False)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000104 file_path = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
105 gclient_scm.os.path.exists(file_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000106
107 self.mox.ReplayAll()
108 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
109 relpath=self.relpath)
110 exception = "Unsupported argument(s): %s" % ','.join(self.args)
111 self.assertRaisesError(exception, scm.RunCommand,
112 'update', options, self.args)
113
114 def testRunCommandUnknown(self):
115 # TODO(maruel): if ever used.
116 pass
117
118 def testRevertMissing(self):
119 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000120 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
121 gclient_scm.os.path.isdir(base_path).AndReturn(False)
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +0000122 gclient_scm.scm.SVN.Capture(['--version']
123 ).AndReturn('svn, version 1.5.1 (r32289)')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000124 # It'll to a checkout instead.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000125 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
126 ).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000127 print("\n_____ %s is missing, synching instead" % self.relpath)
128 # Checkout.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000129 gclient_scm.os.path.exists(base_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000130 files_list = self.mox.CreateMockAnything()
maruel@chromium.org03807072010-08-16 17:18:44 +0000131 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose,
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +0000132 ['checkout', self.url, base_path,
133 '--force'],
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000134 self.root_dir, files_list)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000135
136 self.mox.ReplayAll()
137 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
138 relpath=self.relpath)
139 scm.revert(options, self.args, files_list)
140
141 def testRevertNone(self):
142 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000143 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
144 gclient_scm.os.path.isdir(base_path).AndReturn(True)
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000145 gclient_scm.scm.SVN.CaptureStatus(base_path).AndReturn([])
maruel@chromium.org03807072010-08-16 17:18:44 +0000146 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose,
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000147 ['update', '--revision', 'BASE'],
148 base_path, mox.IgnoreArg())
msb@chromium.orge28e4982009-09-25 20:51:45 +0000149
150 self.mox.ReplayAll()
151 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
152 relpath=self.relpath)
153 file_list = []
154 scm.revert(options, self.args, file_list)
155
156 def testRevert2Files(self):
157 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000158 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
159 gclient_scm.os.path.isdir(base_path).AndReturn(True)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000160 items = [
161 ('M ', 'a'),
162 ('A ', 'b'),
163 ]
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000164 file_path1 = gclient_scm.os.path.join(base_path, 'a')
165 file_path2 = gclient_scm.os.path.join(base_path, 'b')
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000166 gclient_scm.scm.SVN.CaptureStatus(base_path).AndReturn(items)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000167 gclient_scm.os.path.exists(file_path1).AndReturn(True)
168 gclient_scm.os.path.isfile(file_path1).AndReturn(True)
169 gclient_scm.os.remove(file_path1)
170 gclient_scm.os.path.exists(file_path2).AndReturn(True)
171 gclient_scm.os.path.isfile(file_path2).AndReturn(True)
172 gclient_scm.os.remove(file_path2)
maruel@chromium.org03807072010-08-16 17:18:44 +0000173 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose,
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000174 ['update', '--revision', 'BASE'],
175 base_path, mox.IgnoreArg())
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000176 print(gclient_scm.os.path.join(base_path, 'a'))
177 print(gclient_scm.os.path.join(base_path, 'b'))
msb@chromium.orge28e4982009-09-25 20:51:45 +0000178
179 self.mox.ReplayAll()
180 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
181 relpath=self.relpath)
182 file_list = []
183 scm.revert(options, self.args, file_list)
184
185 def testRevertDirectory(self):
186 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000187 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
188 gclient_scm.os.path.isdir(base_path).AndReturn(True)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000189 items = [
190 ('~ ', 'a'),
191 ]
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000192 gclient_scm.scm.SVN.CaptureStatus(base_path).AndReturn(items)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000193 file_path = gclient_scm.os.path.join(base_path, 'a')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000194 print(file_path)
195 gclient_scm.os.path.exists(file_path).AndReturn(True)
196 gclient_scm.os.path.isfile(file_path).AndReturn(False)
msb@chromium.org32906d12010-01-12 18:22:09 +0000197 gclient_scm.os.path.islink(file_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000198 gclient_scm.os.path.isdir(file_path).AndReturn(True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000199 gclient_scm.gclient_utils.RemoveDirectory(file_path)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000200 file_list1 = []
maruel@chromium.org03807072010-08-16 17:18:44 +0000201 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose,
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000202 ['update', '--revision', 'BASE'],
203 base_path, mox.IgnoreArg())
msb@chromium.orge28e4982009-09-25 20:51:45 +0000204
205 self.mox.ReplayAll()
206 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
207 relpath=self.relpath)
208 file_list2 = []
209 scm.revert(options, self.args, file_list2)
210
211 def testStatus(self):
212 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000213 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
214 gclient_scm.os.path.isdir(base_path).AndReturn(True)
maruel@chromium.org03807072010-08-16 17:18:44 +0000215 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose,
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000216 ['status'] + self.args,
217 base_path, []).AndReturn(None)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000218
219 self.mox.ReplayAll()
220 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
221 relpath=self.relpath)
222 file_list = []
223 self.assertEqual(scm.status(options, self.args, file_list), None)
224
225
226 # TODO(maruel): TEST REVISIONS!!!
227 # TODO(maruel): TEST RELOCATE!!!
228 def testUpdateCheckout(self):
229 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000230 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
231 file_info = gclient_scm.gclient_utils.PrintableObject()
msb@chromium.orge28e4982009-09-25 20:51:45 +0000232 file_info.root = 'blah'
233 file_info.url = self.url
234 file_info.uuid = 'ABC'
235 file_info.revision = 42
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000236 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
237 ).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000238 # Checkout.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000239 gclient_scm.os.path.exists(base_path).AndReturn(False)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000240 files_list = self.mox.CreateMockAnything()
maruel@chromium.org03807072010-08-16 17:18:44 +0000241 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose,
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +0000242 ['checkout', self.url, base_path,
243 '--force'],
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000244 self.root_dir, files_list)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000245 self.mox.ReplayAll()
246 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
247 relpath=self.relpath)
248 scm.update(options, (), files_list)
249
250 def testUpdateUpdate(self):
251 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000252 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000253 options.force = True
254 options.nohooks = False
255 file_info = {
256 'Repository Root': 'blah',
257 'URL': self.url,
258 'UUID': 'ABC',
259 'Revision': 42,
260 }
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000261 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
262 ).AndReturn(False)
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000263
264 # Verify no locked files.
265 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
266 ).AndReturn([])
267
msb@chromium.orge28e4982009-09-25 20:51:45 +0000268 # Checkout or update.
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000269 gclient_scm.os.path.exists(base_path).AndReturn(True)
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000270 gclient_scm.scm.SVN.CaptureInfo(
271 gclient_scm.os.path.join(base_path, "."), '.'
272 ).AndReturn(file_info)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000273 # Cheat a bit here.
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000274 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000275 additional_args = []
276 if options.manually_grab_svn_rev:
277 additional_args = ['--revision', str(file_info['Revision'])]
tony@chromium.org99828122010-06-04 01:41:02 +0000278 if options.force and gclient_scm.scm.SVN.AssertVersion("1.5")[0]:
279 additional_args.append('--force')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000280 files_list = []
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000281 gclient_scm.scm.SVN.RunAndGetFileList(
maruel@chromium.org03807072010-08-16 17:18:44 +0000282 options.verbose,
maruel@chromium.org5aeb7dd2009-11-17 18:09:01 +0000283 ['update', base_path] + additional_args,
284 self.root_dir, files_list)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000285
286 self.mox.ReplayAll()
287 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
288 relpath=self.relpath)
289 scm.update(options, (), files_list)
290
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000291 def testUpdateSingleCheckout(self):
292 options = self.Options(verbose=True)
293 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
294 file_info = {
295 'URL': self.url,
296 'Revision': 42,
297 }
tony@chromium.org57564662010-04-14 02:35:12 +0000298
299 # Checks to make sure that we support svn co --depth.
300 gclient_scm.scm.SVN.current_version = None
301 gclient_scm.scm.SVN.Capture(['--version']
302 ).AndReturn('svn, version 1.5.1 (r32289)')
303 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.svn')
304 ).AndReturn(False)
305 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, 'DEPS')
306 ).AndReturn(False)
307
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000308 # Verify no locked files.
309 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
310 ).AndReturn([])
311
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000312 # When checking out a single file, we issue an svn checkout and svn update.
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000313 files_list = self.mox.CreateMockAnything()
314 gclient_scm.scm.SVN.Run(
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +0000315 ['checkout', '--depth', 'empty', self.url, base_path],
316 cwd=self.root_dir)
maruel@chromium.org03807072010-08-16 17:18:44 +0000317 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose, ['update', 'DEPS'],
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000318 gclient_scm.os.path.join(self.root_dir, self.relpath), files_list)
319
320 # Now we fall back on scm.update().
321 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
tony@chromium.org57564662010-04-14 02:35:12 +0000322 ).AndReturn(False)
323 gclient_scm.os.path.exists(base_path).AndReturn(True)
324 gclient_scm.scm.SVN.CaptureInfo(
325 gclient_scm.os.path.join(base_path, "."), '.'
326 ).AndReturn(file_info)
327 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
328 print("\n_____ %s at 42" % self.relpath)
329
330 self.mox.ReplayAll()
331 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
332 relpath=self.relpath)
333 scm.updatesingle(options, ['DEPS'], files_list)
334
335 def testUpdateSingleCheckoutSVN14(self):
336 options = self.Options(verbose=True)
337 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
338 file_info = {
339 'URL': self.url,
340 'Revision': 42,
341 }
342
343 # Checks to make sure that we support svn co --depth.
344 gclient_scm.scm.SVN.current_version = None
345 gclient_scm.scm.SVN.Capture(['--version']
346 ).AndReturn('svn, version 1.4.4 (r25188)')
347 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path)
348 ).AndReturn(True)
349
350 # When checking out a single file with svn 1.4, we use svn export
351 files_list = self.mox.CreateMockAnything()
352 gclient_scm.scm.SVN.Run(
353 ['export', gclient_scm.os.path.join(self.url, 'DEPS'),
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +0000354 gclient_scm.os.path.join(base_path, 'DEPS')],
355 cwd=self.root_dir)
tony@chromium.org57564662010-04-14 02:35:12 +0000356
357 self.mox.ReplayAll()
358 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
359 relpath=self.relpath)
360 scm.updatesingle(options, ['DEPS'], files_list)
361
362 def testUpdateSingleCheckoutSVNUpgrade(self):
363 options = self.Options(verbose=True)
364 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
365 file_info = {
366 'URL': self.url,
367 'Revision': 42,
368 }
369
370 # Checks to make sure that we support svn co --depth.
371 gclient_scm.scm.SVN.current_version = None
372 gclient_scm.scm.SVN.Capture(['--version']
373 ).AndReturn('svn, version 1.5.1 (r32289)')
374 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.svn')
375 ).AndReturn(False)
376 # If DEPS already exists, assume we're upgrading from svn1.4, so delete
377 # the old DEPS file.
378 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, 'DEPS')
379 ).AndReturn(True)
380 gclient_scm.os.remove(gclient_scm.os.path.join(base_path, 'DEPS'))
381
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000382 # Verify no locked files.
383 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
384 ).AndReturn([])
385
tony@chromium.org57564662010-04-14 02:35:12 +0000386 # When checking out a single file, we issue an svn checkout and svn update.
387 files_list = self.mox.CreateMockAnything()
388 gclient_scm.scm.SVN.Run(
maruel@chromium.org2b9aa8e2010-08-25 20:01:42 +0000389 ['checkout', '--depth', 'empty', self.url, base_path],
390 cwd=self.root_dir)
maruel@chromium.org03807072010-08-16 17:18:44 +0000391 gclient_scm.scm.SVN.RunAndGetFileList(options.verbose, ['update', 'DEPS'],
tony@chromium.org57564662010-04-14 02:35:12 +0000392 gclient_scm.os.path.join(self.root_dir, self.relpath), files_list)
393
394 # Now we fall back on scm.update().
395 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
396 ).AndReturn(False)
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000397 gclient_scm.os.path.exists(base_path).AndReturn(True)
398 gclient_scm.scm.SVN.CaptureInfo(
399 gclient_scm.os.path.join(base_path, "."), '.'
400 ).AndReturn(file_info)
401 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
402 print("\n_____ %s at 42" % self.relpath)
403
404 self.mox.ReplayAll()
405 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
406 relpath=self.relpath)
407 scm.updatesingle(options, ['DEPS'], files_list)
408
409 def testUpdateSingleUpdate(self):
410 options = self.Options(verbose=True)
411 base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
412 file_info = {
413 'URL': self.url,
414 'Revision': 42,
415 }
tony@chromium.org57564662010-04-14 02:35:12 +0000416 # Checks to make sure that we support svn co --depth.
417 gclient_scm.scm.SVN.current_version = None
418 gclient_scm.scm.SVN.Capture(['--version']
419 ).AndReturn('svn, version 1.5.1 (r32289)')
420 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.svn')
421 ).AndReturn(True)
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000422
maruel@chromium.orge407c9a2010-08-09 19:11:37 +0000423 # Verify no locked files.
424 gclient_scm.scm.SVN.CaptureStatus(gclient_scm.os.path.join(base_path, '.')
425 ).AndReturn([])
426
tony@chromium.org4b5b1772010-04-08 01:52:56 +0000427 # Now we fall back on scm.update().
428 files_list = self.mox.CreateMockAnything()
429 gclient_scm.os.path.exists(gclient_scm.os.path.join(base_path, '.git')
430 ).AndReturn(False)
431 gclient_scm.os.path.exists(base_path).AndReturn(True)
432 gclient_scm.scm.SVN.CaptureInfo(
433 gclient_scm.os.path.join(base_path, "."), '.'
434 ).AndReturn(file_info)
435 gclient_scm.scm.SVN.CaptureInfo(file_info['URL'], '.').AndReturn(file_info)
436 print("\n_____ %s at 42" % self.relpath)
437
438 self.mox.ReplayAll()
439 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
440 relpath=self.relpath)
441 scm.updatesingle(options, ['DEPS'], files_list)
442
msb@chromium.orge28e4982009-09-25 20:51:45 +0000443 def testUpdateGit(self):
444 options = self.Options(verbose=True)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000445 file_path = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
446 gclient_scm.os.path.exists(file_path).AndReturn(True)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000447 print("________ found .git directory; skipping %s" % self.relpath)
448
449 self.mox.ReplayAll()
450 scm = self._scm_wrapper(url=self.url, root_dir=self.root_dir,
451 relpath=self.relpath)
452 file_list = []
453 scm.update(options, self.args, file_list)
454
msb@chromium.orge28e4982009-09-25 20:51:45 +0000455
msb@chromium.org5bde4852009-12-14 16:47:12 +0000456class GitWrapperTestCase(BaseTestCase):
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000457 """This class doesn't use pymox."""
msb@chromium.orge28e4982009-09-25 20:51:45 +0000458 class OptionsObject(object):
459 def __init__(self, test_case, verbose=False, revision=None):
460 self.verbose = verbose
461 self.revision = revision
462 self.manually_grab_svn_rev = True
463 self.deps_os = None
464 self.force = False
davemoore@chromium.org8bf27312010-02-19 17:29:44 +0000465 self.reset = False
msb@chromium.orge28e4982009-09-25 20:51:45 +0000466 self.nohooks = False
467
468 sample_git_import = """blob
469mark :1
470data 6
471Hello
472
473blob
474mark :2
475data 4
476Bye
477
478reset refs/heads/master
479commit refs/heads/master
480mark :3
481author Bob <bob@example.com> 1253744361 -0700
482committer Bob <bob@example.com> 1253744361 -0700
483data 8
484A and B
485M 100644 :1 a
486M 100644 :2 b
487
488blob
489mark :4
490data 10
491Hello
492You
493
494blob
495mark :5
496data 8
497Bye
498You
499
500commit refs/heads/origin
501mark :6
502author Alice <alice@example.com> 1253744424 -0700
503committer Alice <alice@example.com> 1253744424 -0700
504data 13
505Personalized
506from :3
507M 100644 :4 a
508M 100644 :5 b
509
510reset refs/heads/master
511from :3
512"""
msb@chromium.orge28e4982009-09-25 20:51:45 +0000513 def Options(self, *args, **kwargs):
514 return self.OptionsObject(self, *args, **kwargs)
515
516 def CreateGitRepo(self, git_import, path):
maruel@chromium.orgd5800f12009-11-12 20:03:43 +0000517 """Do it for real."""
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000518 try:
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000519 Popen(['git', 'init'], stdout=PIPE, stderr=STDOUT,
520 cwd=path).communicate()
521 except OSError:
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000522 # git is not available, skip this test.
523 return False
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000524 Popen(['git', 'fast-import'], stdin=PIPE, stdout=PIPE, stderr=STDOUT,
525 cwd=path).communicate(input=git_import)
526 Popen(['git', 'checkout'], stdout=PIPE, stderr=STDOUT,
527 cwd=path).communicate()
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000528 Popen(['git', 'remote', 'add', '-f', 'origin', '.'], stdout=PIPE,
529 stderr=STDOUT, cwd=path).communicate()
530 Popen(['git', 'checkout', '-b', 'new', 'origin/master'], stdout=PIPE,
531 stderr=STDOUT, cwd=path).communicate()
532 Popen(['git', 'push', 'origin', 'origin/origin:origin/master'], stdout=PIPE,
533 stderr=STDOUT, cwd=path).communicate()
534 Popen(['git', 'config', '--unset', 'remote.origin.fetch'], stdout=PIPE,
535 stderr=STDOUT, cwd=path).communicate()
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000536 return True
msb@chromium.orge28e4982009-09-25 20:51:45 +0000537
msb@chromium.orge28e4982009-09-25 20:51:45 +0000538 def setUp(self):
msb@chromium.orge28e4982009-09-25 20:51:45 +0000539 self.args = self.Args()
540 self.url = 'git://foo'
541 self.root_dir = tempfile.mkdtemp()
542 self.relpath = '.'
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000543 self.base_path = gclient_scm.os.path.join(self.root_dir, self.relpath)
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000544 self.enabled = self.CreateGitRepo(self.sample_git_import, self.base_path)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000545 SuperMoxBaseTestBase.setUp(self)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000546
547 def tearDown(self):
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000548 SuperMoxBaseTestBase.tearDown(self)
maruel@chromium.orgba551772010-02-03 18:21:42 +0000549 rmtree(self.root_dir)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000550
551 def testDir(self):
552 members = [
maruel@chromium.org55e724e2010-03-11 19:36:49 +0000553 'FullUrlForRelativeUrl', 'RunCommand',
msb@chromium.orge6f78352010-01-13 17:05:33 +0000554 'cleanup', 'diff', 'export', 'pack', 'relpath', 'revert',
maruel@chromium.org9eda4112010-06-11 18:56:10 +0000555 'revinfo', 'runhooks', 'status', 'update', 'url',
msb@chromium.orge28e4982009-09-25 20:51:45 +0000556 ]
557
558 # If you add a member, be sure to add the relevant test!
559 self.compareMembers(gclient_scm.CreateSCM(url=self.url), members)
560
561 def testRevertMissing(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000562 if not self.enabled:
563 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000564 options = self.Options()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000565 file_path = gclient_scm.os.path.join(self.base_path, 'a')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000566 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
567 relpath=self.relpath)
568 file_list = []
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000569 scm.update(options, None, file_list)
570 gclient_scm.os.remove(file_path)
571 file_list = []
msb@chromium.orge28e4982009-09-25 20:51:45 +0000572 scm.revert(options, self.args, file_list)
573 self.assertEquals(file_list, [file_path])
574 file_list = []
575 scm.diff(options, self.args, file_list)
576 self.assertEquals(file_list, [])
577
578 def testRevertNone(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000579 if not self.enabled:
580 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000581 options = self.Options()
582 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
583 relpath=self.relpath)
584 file_list = []
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000585 scm.update(options, None, file_list)
586 file_list = []
msb@chromium.orge28e4982009-09-25 20:51:45 +0000587 scm.revert(options, self.args, file_list)
588 self.assertEquals(file_list, [])
msb@chromium.org0f282062009-11-06 20:14:02 +0000589 self.assertEquals(scm.revinfo(options, self.args, None),
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000590 'a7142dc9f0009350b96a11f372b6ea658592aa95')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000591
592
593 def testRevertModified(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000594 if not self.enabled:
595 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000596 options = self.Options()
msb@chromium.orge28e4982009-09-25 20:51:45 +0000597 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
598 relpath=self.relpath)
599 file_list = []
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000600 scm.update(options, None, file_list)
601 file_path = gclient_scm.os.path.join(self.base_path, 'a')
602 open(file_path, 'a').writelines('touched\n')
603 file_list = []
msb@chromium.orge28e4982009-09-25 20:51:45 +0000604 scm.revert(options, self.args, file_list)
605 self.assertEquals(file_list, [file_path])
606 file_list = []
607 scm.diff(options, self.args, file_list)
608 self.assertEquals(file_list, [])
msb@chromium.org0f282062009-11-06 20:14:02 +0000609 self.assertEquals(scm.revinfo(options, self.args, None),
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000610 'a7142dc9f0009350b96a11f372b6ea658592aa95')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000611
612 def testRevertNew(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000613 if not self.enabled:
614 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000615 options = self.Options()
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000616 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
617 relpath=self.relpath)
618 file_list = []
619 scm.update(options, None, file_list)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000620 file_path = gclient_scm.os.path.join(self.base_path, 'c')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000621 f = open(file_path, 'w')
622 f.writelines('new\n')
623 f.close()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000624 Popen(['git', 'add', 'c'], stdout=PIPE,
625 stderr=STDOUT, cwd=self.base_path).communicate()
msb@chromium.orge28e4982009-09-25 20:51:45 +0000626 file_list = []
627 scm.revert(options, self.args, file_list)
628 self.assertEquals(file_list, [file_path])
629 file_list = []
630 scm.diff(options, self.args, file_list)
631 self.assertEquals(file_list, [])
msb@chromium.org0f282062009-11-06 20:14:02 +0000632 self.assertEquals(scm.revinfo(options, self.args, None),
nasser@codeaurora.orgb2b46312010-04-30 20:58:03 +0000633 'a7142dc9f0009350b96a11f372b6ea658592aa95')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000634
635 def testStatusNew(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000636 if not self.enabled:
637 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000638 options = self.Options()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000639 file_path = gclient_scm.os.path.join(self.base_path, 'a')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000640 open(file_path, 'a').writelines('touched\n')
641 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
642 relpath=self.relpath)
643 file_list = []
644 scm.status(options, self.args, file_list)
645 self.assertEquals(file_list, [file_path])
646
647 def testStatus2New(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000648 if not self.enabled:
649 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000650 options = self.Options()
651 expected_file_list = []
652 for f in ['a', 'b']:
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000653 file_path = gclient_scm.os.path.join(self.base_path, f)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000654 open(file_path, 'a').writelines('touched\n')
655 expected_file_list.extend([file_path])
656 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
657 relpath=self.relpath)
658 file_list = []
659 scm.status(options, self.args, file_list)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000660 expected_file_list = [gclient_scm.os.path.join(self.base_path, x)
661 for x in ['a', 'b']]
msb@chromium.orge28e4982009-09-25 20:51:45 +0000662 self.assertEquals(sorted(file_list), expected_file_list)
663
664 def testUpdateCheckout(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000665 if not self.enabled:
666 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000667 options = self.Options(verbose=True)
668 root_dir = tempfile.mkdtemp()
669 relpath = 'foo'
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000670 base_path = gclient_scm.os.path.join(root_dir, relpath)
671 url = gclient_scm.os.path.join(self.root_dir, self.relpath, '.git')
msb@chromium.orge28e4982009-09-25 20:51:45 +0000672 try:
673 scm = gclient_scm.CreateSCM(url=url, root_dir=root_dir,
674 relpath=relpath)
675 file_list = []
676 scm.update(options, (), file_list)
677 self.assertEquals(len(file_list), 2)
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000678 self.assert_(gclient_scm.os.path.isfile(
679 gclient_scm.os.path.join(base_path, 'a')))
msb@chromium.org0f282062009-11-06 20:14:02 +0000680 self.assertEquals(scm.revinfo(options, (), None),
msb@chromium.orge28e4982009-09-25 20:51:45 +0000681 '069c602044c5388d2d15c3f875b057c852003458')
682 finally:
maruel@chromium.orgba551772010-02-03 18:21:42 +0000683 rmtree(root_dir)
msb@chromium.orge28e4982009-09-25 20:51:45 +0000684
685 def testUpdateUpdate(self):
maruel@chromium.orgea6c2c52009-10-09 20:38:14 +0000686 if not self.enabled:
687 return
msb@chromium.orge28e4982009-09-25 20:51:45 +0000688 options = self.Options()
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000689 expected_file_list = [gclient_scm.os.path.join(self.base_path, x)
690 for x in ['a', 'b']]
msb@chromium.orge28e4982009-09-25 20:51:45 +0000691 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
692 relpath=self.relpath)
693 file_list = []
694 scm.update(options, (), file_list)
msb@chromium.org0f282062009-11-06 20:14:02 +0000695 self.assertEquals(file_list, expected_file_list)
696 self.assertEquals(scm.revinfo(options, (), None),
msb@chromium.orge28e4982009-09-25 20:51:45 +0000697 'a7142dc9f0009350b96a11f372b6ea658592aa95')
698
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000699 def testUpdateUnstagedConflict(self):
700 if not self.enabled:
701 return
702 options = self.Options()
703 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
704 relpath=self.relpath)
705 file_path = gclient_scm.os.path.join(self.base_path, 'b')
706 f = open(file_path, 'w').writelines('conflict\n')
707 exception = (
708 "error: Your local changes to 'b' would be overwritten by merge. "
709 "Aborting.\n"
710 "Please, commit your changes or stash them before you can merge.\n")
711 self.assertRaisesError(exception, scm.update, options, (), [])
712
msb@chromium.org5bde4852009-12-14 16:47:12 +0000713 def testUpdateConflict(self):
714 if not self.enabled:
715 return
716 options = self.Options()
717 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
718 relpath=self.relpath)
719 file_path = gclient_scm.os.path.join(self.base_path, 'b')
720 f = open(file_path, 'w').writelines('conflict\n')
721 scm._Run(['commit', '-am', 'test'])
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000722 self.mox.StubOutWithMock(__builtin__, 'raw_input')
723 __builtin__.raw_input.__call__(mox.StrContains('Cannot fast-forward merge, '
724 'attempt to rebase? (y)es / '
725 '(q)uit / (s)kip : ')
726 ).AndReturn('y')
727 self.mox.ReplayAll()
msb@chromium.org5bde4852009-12-14 16:47:12 +0000728 exception = \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000729 'Conflict while rebasing this branch.\n' \
msb@chromium.org5bde4852009-12-14 16:47:12 +0000730 'Fix the conflict and run gclient again.\n' \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000731 "See 'man git-rebase' for details.\n"
msb@chromium.org5bde4852009-12-14 16:47:12 +0000732 self.assertRaisesError(exception, scm.update, options, (), [])
733 exception = \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000734 '\n____ . at refs/heads/master\n' \
msb@chromium.org786fb682010-06-02 15:16:23 +0000735 '\tYou have unstaged changes.\n' \
736 '\tPlease commit, stash, or reset.\n'
msb@chromium.org5bde4852009-12-14 16:47:12 +0000737 self.assertRaisesError(exception, scm.update, options, (), [])
738
msb@chromium.orge4af1ab2010-01-13 21:26:09 +0000739 def testUpdateNotGit(self):
740 if not self.enabled:
741 return
742 options = self.Options()
743 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
744 relpath=self.relpath)
745 git_path = gclient_scm.os.path.join(self.base_path, '.git')
maruel@chromium.orgba551772010-02-03 18:21:42 +0000746 rename(git_path, git_path + 'foo')
msb@chromium.orge4af1ab2010-01-13 21:26:09 +0000747 exception = \
nasser@codeaurora.orgd90ba3f2010-02-23 14:42:57 +0000748 '\n____ . at refs/heads/master\n' \
msb@chromium.orge4af1ab2010-01-13 21:26:09 +0000749 '\tPath is not a git repo. No .git dir.\n' \
750 '\tTo resolve:\n' \
751 '\t\trm -rf .\n' \
752 '\tAnd run gclient sync again\n'
753 self.assertRaisesError(exception, scm.update, options, (), [])
754
msb@chromium.org0f282062009-11-06 20:14:02 +0000755 def testRevinfo(self):
756 if not self.enabled:
757 return
758 options = self.Options()
759 scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
760 relpath=self.relpath)
761 rev_info = scm.revinfo(options, (), None)
762 self.assertEquals(rev_info, '069c602044c5388d2d15c3f875b057c852003458')
763
msb@chromium.orge28e4982009-09-25 20:51:45 +0000764
msb@chromium.orge28e4982009-09-25 20:51:45 +0000765if __name__ == '__main__':
maruel@chromium.org8ef5f542009-11-12 02:05:02 +0000766 import unittest
msb@chromium.orge28e4982009-09-25 20:51:45 +0000767 unittest.main()
768
769# vim: ts=2:sw=2:tw=80:et: