From 3365c913c42bc015d5fcdb7275a234a9f53fe828 Mon Sep 17 00:00:00 2001 From: "maruel@chromium.org" Date: Wed, 26 May 2010 17:47:06 +0000 Subject: [PATCH] Reapply 48271 with fix. """ Enable automatic command and one-liner doc. Reformat pydoc accordingly. Add parser as an argument and parse_args hook in preparation to move parse_args at the right place, inside the CMDxx functions. R.I.P. gclient_test.py """ original code review at: http://codereview.chromium.org/2253002 In addition: - Add more smoke tests: vars, hooks, runhooks - Bugs filed about misbehavior with git checkout - Fixed gclient runhooks TEST=smoke test BUG=23328 Review URL: http://codereview.chromium.org/2265002 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@48289 0039d316-1c4b-4281-b951-d872f2087c98 --- PRESUBMIT.py | 1 - gclient.py | 332 ++++------ tests/fake_repos.py | 48 +- tests/gclient_smoketest.py | 158 +++-- tests/gclient_test.py | 1273 ------------------------------------ 5 files changed, 285 insertions(+), 1527 deletions(-) delete mode 100755 tests/gclient_test.py diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 07c4842ca..59b25bd45 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -10,7 +10,6 @@ details on the presubmit API built into gcl. UNIT_TESTS = [ 'tests.gcl_unittest', - 'tests.gclient_test', 'tests.gclient_scm_test', 'tests.gclient_utils_test', 'tests.presubmit_unittest', diff --git a/gclient.py b/gclient.py index e7672a14b..f425d1da3 100644 --- a/gclient.py +++ b/gclient.py @@ -55,7 +55,7 @@ Hooks ] """ -__version__ = "0.3.7" +__version__ = "0.4" import errno import logging @@ -73,22 +73,6 @@ import gclient_scm import gclient_utils from third_party.repo.progress import Progress -# default help text -DEFAULT_USAGE_TEXT = ( -"""%prog [options] [--] [SCM options/args...] -a wrapper for managing a set of svn client modules and/or git repositories. -Version """ + __version__ + """ - -Options and extra arguments can be passed to invoked SCM commands by -appending them to the command line. Note that if the first such -appended option starts with a dash (-) then the options must be -preceded by -- to distinguish them from gclient options. - -For additional help on a subcommand or examples of usage, try - %prog help - %prog help files -""") - def attr(attr, data): """Sets an attribute on a function.""" @@ -470,6 +454,8 @@ solutions = [ def _RunHookAction(self, hook_dict, matching_file_list): """Runs the action from a single hook. """ + logging.info(hook_dict) + logging.info(matching_file_list) command = hook_dict['action'][:] if command[0] == 'python': # If the hook specified "python" as the first item, the action is a @@ -813,19 +799,15 @@ solutions = [ print(snapclient._config_content) -## gclient commands. - +#### gclient commands. -def CMDcleanup(parser, options, args): - """Clean up all working copies, using 'svn cleanup' for each module. -Additional options and args may be passed to 'svn cleanup'. +def CMDcleanup(parser, args): + """Cleans up all working copies. -usage: cleanup [options] [--] [svn cleanup args/options] - -Valid options: - --verbose : output additional diagnostics +Mostly svn-specific. Simply runs 'svn cleanup' for each module. """ + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") @@ -836,32 +818,23 @@ Valid options: return client.RunOnDeps('cleanup', args) -def CMDconfig(parser, options, args): +@attr('usage', '[url] [safesync url]') +def CMDconfig(parser, args): """Create a .gclient file in the current directory. -This specifies the configuration for further commands. After update/sync, +This specifies the configuration for further commands. After update/sync, top-level DEPS files in each module are read to determine dependent -modules to operate on as well. If optional [url] parameter is +modules to operate on as well. If optional [url] parameter is provided, then configuration is read from a specified Subversion server -URL. Otherwise, a --spec option must be provided. A --name option overrides -the default name for the solutions. - -usage: config [option | url] [safesync url] - -Valid options: - --name path : alternate relative path for the solution - --spec=GCLIENT_SPEC : contents of .gclient are read from string parameter. - *Note that due to Cygwin/Python brokenness, it - probably can't contain any newlines.* - -Examples: - gclient config https://gclient.googlecode.com/svn/trunk/gclient - configure a new client to check out gclient.py tool sources - gclient config --name tools https://gclient.googlecode.com/svn/trunk/gclient - gclient config --spec='solutions=[{"name":"gclient", - '"url":"https://gclient.googlecode.com/svn/trunk/gclient",' - '"custom_deps":{}}]' +URL. """ + parser.add_option("--spec", + help="create a gclient file containing the provided " + "string. Due to Cygwin/Python brokenness, it " + "probably can't contain any newlines.") + parser.add_option("--name", + help="overrides the default name for the solution") + (options, args) = parser.parse_args(args) if len(args) < 1 and not options.spec: raise gclient_utils.Error("required argument missing; see 'gclient help " "config'") @@ -886,8 +859,9 @@ Examples: return 0 -def CMDexport(parser, options, args): +def CMDexport(parser, args): """Wrapper for svn export for all managed directories.""" + (options, args) = parser.parse_args(args) if len(args) != 1: raise gclient_utils.Error("Need directory name") client = GClient.LoadCurrentConfig(options) @@ -902,30 +876,19 @@ def CMDexport(parser, options, args): return client.RunOnDeps('export', args) -def CMDpack(parser, options, args): +@attr('epilog', """Example: + gclient pack > patch.txt + generate simple patch for configured client and dependences +""") +def CMDpack(parser, args): """Generate a patch which can be applied at the root of the tree. -Internally, runs 'svn diff' on each checked out module and +Internally, runs 'svn diff'/'git diff' on each checked out module and dependencies, and performs minimal postprocessing of the output. The resulting patch is printed to stdout and can be applied to a freshly -checked out tree via 'patch -p0 < patchfile'. Additional args and -options to 'svn diff' can be passed after gclient options. - -usage: pack [options] [--] [svn args/options] - -Valid options: - --verbose : output additional diagnostics - -Examples: - gclient pack > patch.txt - generate simple patch for configured client and dependences - gclient pack -- -x -b > patch.txt - generate patch using 'svn diff -x -b' to suppress - whitespace-only differences - gclient pack -- -r HEAD -x -b > patch.txt - generate patch, diffing each file versus the latest version of - each module +checked out tree via 'patch -p0 < patchfile'. """ + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") @@ -936,17 +899,9 @@ Examples: return client.RunOnDeps('pack', args) -def CMDstatus(parser, options, args): - """Show the modification status of for every dependencies. - -Additional options and args may be passed to 'svn status'. - -usage: status [options] [--] [svn diff args/options] - -Valid options: - --verbose : output additional diagnostics - --nohooks : don't run the hooks after the update is complete -""" +def CMDstatus(parser, args): + """Show modification status for every dependencies.""" + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") @@ -957,31 +912,7 @@ Valid options: return client.RunOnDeps('status', args) -def CMDsync(parser, options, args): - """Checkout/update the modules specified by the gclient configuration. - -Unless --revision is specified, then the latest revision of the root solutions -is checked out, with dependent submodule versions updated according to DEPS -files. If --revision is specified, then the given revision is used in place -of the latest, either for a single solution or for all solutions. -Unless the --force option is provided, solutions and modules whose -local revision matches the one to update (i.e., they have not changed -in the repository) are *not* modified. Unless --nohooks is provided, -the hooks are run. See 'help config' for more information. - -usage: gclient sync [options] [--] [SCM update options/args] - -Valid options: - --force : force update even for unchanged modules - --nohooks : don't run the hooks after the update is complete - --revision SOLUTION@REV : update given solution to specified revision - --deps PLATFORM(S) : sync deps for the given platform(s), or 'all' - --verbose : output additional diagnostics - --head : update to latest revision, instead of last good - revision - --reset : resets any local changes before updating (git only) - -Examples: +@attr('epilog', """Examples: gclient sync update files from SCM according to current configuration, *for modules which have changed since last update or sync* @@ -990,7 +921,33 @@ Examples: all modules (useful for recovering files deleted from local copy) gclient sync --revision src@31000 update src directory to r31000 -""" +""") +def CMDsync(parser, args): + """Checkout/update all modules.""" + parser.add_option("--force", action="store_true", + help="force update even for unchanged modules") + parser.add_option("--nohooks", action="store_true", + help="don't run hooks after the update is complete") + parser.add_option("-r", "--revision", action="append", + dest="revisions", metavar="REV", default=[], + help="update given solution to specified revision, " + "can be used multiple times for each solution, " + "e.g. -r src@123, -r internal@32") + parser.add_option("--head", action="store_true", + help="skips any safesync_urls specified in " + "configured solutions and sync to head instead") + parser.add_option("--delete_unversioned_trees", action="store_true", + help="delete any unexpected unversioned trees " + "that are in the checkout") + parser.add_option("--reset", action="store_true", + help="resets any local changes before updating (git only)") + parser.add_option("--deps", dest="deps_os", metavar="OS_LIST", + help="sync deps for the specified (comma-separated) " + "platform(s); 'all' will sync all platforms") + parser.add_option("--manually_grab_svn_rev", action="store_true", + help="Skip svn up whenever possible by requesting " + "actual HEAD revision from the repository") + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: @@ -1023,31 +980,13 @@ Examples: return client.RunOnDeps('update', args) -def CMDupdate(parser, options, args): +def CMDupdate(parser, args): """Alias for the sync command. Deprecated.""" - return CMDsync(parser, options, args) - - -def CMDdiff(parser, options, args): - """Display the differences between two revisions of modules. + return CMDsync(parser, args) -(Does 'svn diff' for each checked out module and dependences.) -Additional args and options to 'svn diff' can be passed after -gclient options. - -usage: diff [options] [--] [svn args/options] - -Valid options: - --verbose : output additional diagnostics - -Examples: - gclient diff - simple 'svn diff' for configured client and dependences - gclient diff -- -x -b - use 'svn diff -x -b' to suppress whitespace-only differences - gclient diff -- -r HEAD -x -b - diff versus the latest version of each module -""" +def CMDdiff(parser, args): + """Displays local diff for every dependencies.""" + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") @@ -1058,24 +997,24 @@ Examples: return client.RunOnDeps('diff', args) -def CMDrevert(parser, options, args): - """Revert every file in every managed directory in the client view.""" +def CMDrevert(parser, args): + """Revert all modifications in every dependencies.""" + parser.add_option("--nohooks", action="store_true", + help="don't run hooks after the revert is complete") + (options, args) = parser.parse_args(args) + # --force is implied. + options.force = True client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") return client.RunOnDeps('revert', args) -def CMDrunhooks(parser, options, args): - """Runs hooks for files that have been modified in the local working copy. - -Implies --force. - -usage: runhooks [options] - -Valid options: - --verbose : output additional diagnostics -""" +def CMDrunhooks(parser, args): + """Runs hooks for files that have been modified in the local working copy.""" + parser.add_option("--force", action="store_true", default=True, + help="Deprecated. No effect.") + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") @@ -1084,18 +1023,16 @@ Valid options: # client dict, but more legible, and it might contain helpful comments. print(client.ConfigContent()) options.force = True + options.nohooks = False return client.RunOnDeps('runhooks', args) -def CMDrevinfo(parser, options, args): - """Outputs defails for every dependencies. - -This includes source path, server URL and revision information for every -dependency in all solutions. - -usage: revinfo [options] -""" - __pychecker__ = 'unusednames=args' +def CMDrevinfo(parser, args): + """Outputs details for every dependencies.""" + parser.add_option("--snapshot", action="store_true", + help="create a snapshot file of the current " + "version of all repositories") + (options, args) = parser.parse_args(args) client = GClient.LoadCurrentConfig(options) if not client: raise gclient_utils.Error("client not configured; see 'gclient config'") @@ -1103,70 +1040,45 @@ usage: revinfo [options] return 0 -def CMDhelp(parser, options, args): - """Prints general help or command-specific documentation.""" +def Command(name): + return getattr(sys.modules[__name__], 'CMD' + name, None) + + +def CMDhelp(parser, args): + """Prints list of commands or help for a specific command.""" + (options, args) = parser.parse_args(args) if len(args) == 1: - command = Command(args[0]) - if command: - print getattr(sys.modules[__name__], 'CMD' + args[0]).__doc__ - return 0 - parser.usage = (DEFAULT_USAGE_TEXT + '\nCommands are:\n' + '\n'.join([ - ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip()) - for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')])) + return Main(args + ['--help']) parser.print_help() return 0 -def Command(command): - return getattr(sys.modules[__name__], 'CMD' + command, CMDhelp) +def GenUsage(parser, command): + """Modify an OptParse object with the function's documentation.""" + obj = Command(command) + if command == 'help': + command = '' + # OptParser.description prefer nicely non-formatted strings. + parser.description = re.sub('[\r\n ]{2,}', ' ', obj.__doc__) + usage = getattr(obj, 'usage', '') + parser.set_usage('%%prog %s [options] %s' % (command, usage)) + parser.epilog = getattr(obj, 'epilog', None) def Main(argv): - parser = optparse.OptionParser(usage=DEFAULT_USAGE_TEXT, - version='%prog ' + __version__) + """Doesn't parse the arguments here, just find the right subcommand to + execute.""" + # Do it late so all commands are listed. + CMDhelp.usage = ('\n\nCommands are:\n' + '\n'.join([ + ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip()) + for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')])) + parser = optparse.OptionParser(version='%prog ' + __version__) parser.add_option("-v", "--verbose", action="count", default=0, help="Produces additional output for diagnostics. Can be " "used up to three times for more logging info.") parser.add_option("--gclientfile", metavar="FILENAME", dest="config_filename", default=os.environ.get("GCLIENT_FILE", ".gclient"), help="Specify an alternate .gclient file") - # The other options will be moved eventually. - parser.add_option("--force", action="store_true", - help="(update/sync only) force update even " - "for modules which haven't changed") - parser.add_option("--nohooks", action="store_true", - help="(update/sync/revert only) prevent the hooks " - "from running") - parser.add_option("--revision", action="append", dest="revisions", - metavar="REV", default=[], - help="(update/sync only) sync to a specific " - "revision, can be used multiple times for " - "each solution, e.g. --revision=src@123, " - "--revision=internal@32") - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST", - help="(update/sync only) sync deps for the " - "specified (comma-separated) platform(s); " - "'all' will sync all platforms") - parser.add_option("--reset", action="store_true", - help="(update/sync only) resets any local changes " - "before updating (git only)") - parser.add_option("--spec", - help="(config only) create a gclient file " - "containing the provided string") - parser.add_option("--manually_grab_svn_rev", action="store_true", - help="Skip svn up whenever possible by requesting " - "actual HEAD revision from the repository") - parser.add_option("--head", action="store_true", - help="skips any safesync_urls specified in " - "configured solutions") - parser.add_option("--delete_unversioned_trees", action="store_true", - help="on update, delete any unexpected " - "unversioned trees that are in the checkout") - parser.add_option("--snapshot", action="store_true", - help="(revinfo only), create a snapshot file " - "of the current version of all repositories") - parser.add_option("--name", - help="specify alternate relative solution path") # Integrate standard options processing. old_parser = parser.parse_args def Parse(args): @@ -1176,22 +1088,22 @@ def Main(argv): elif options.verbose > 2: logging.basicConfig(level=logging.DEBUG) options.entries_filename = options.config_filename + "_entries" + if not hasattr(options, 'revisions'): + # GClient.RunOnDeps expects it even if not applicable. + options.revisions = [] return (options, args) parser.parse_args = Parse # We don't want wordwrapping in epilog (usually examples) parser.format_epilog = lambda _: parser.epilog or '' - - if not len(argv): - argv = ['help'] - # Add manual support for --version as first argument. - if argv[0] == '--version': - parser.print_version() - return 0 - # Add manual support for --help as first argument. - if argv[0] == '--help': - argv[0] = 'help' - options, args = parser.parse_args(argv[1:]) - return Command(argv[0])(parser, options, args) + if argv: + command = Command(argv[0]) + if command: + # "fix" the usage and the description now that we know the subcommand. + GenUsage(parser, argv[0]) + return command(parser, argv[1:]) + # Not a known command. Default to help. + GenUsage(parser, 'help') + return CMDhelp(parser, argv) if "__main__" == __name__: diff --git a/tests/fake_repos.py b/tests/fake_repos.py index 852f99552..0ce6296e4 100755 --- a/tests/fake_repos.py +++ b/tests/fake_repos.py @@ -205,14 +205,19 @@ class FakeRepos(object): # - versioned and unversioned reference # - relative and full reference # - deps_os - # TODO(maruel): # - var # - hooks + # TODO(maruel): # - File + # - $matching_files + # - use_relative_paths self._commit_svn(file_system(1, """ +vars = { + 'DummyVariable': 'third_party', +} deps = { 'src/other': 'svn://%(host)s/svn/trunk/other', - 'src/third_party/fpp': '/trunk/third_party/foo', + 'src/third_party/fpp': '/trunk/' + Var('DummyVariable') + '/foo', } deps_os = { 'mac': { @@ -225,6 +230,21 @@ deps = { 'src/other': 'svn://%(host)s/svn/trunk/other', 'src/third_party/foo': '/trunk/third_party/foo@1', } +# I think this is wrong to have the hooks run from the base of the gclient +# checkout. It's maybe a bit too late to change that behavior. +hooks = [ + { + 'pattern': '.', + 'action': ['python', '-c', + 'open(\\'src/hooked1\\', \\'w\\').write(\\'hooked1\\')'], + }, + { + # Should not be run. + 'pattern': 'nonexistent', + 'action': ['python', '-c', + 'open(\\'src/hooked2\\', \\'w\\').write(\\'hooked2\\')'], + }, +] """ % { 'host': '127.0.0.1' })) def setUpGIT(self): @@ -241,15 +261,20 @@ deps = { # - versioned and unversioned reference # - relative and full reference # - deps_os - # TODO(maruel): # - var # - hooks + # TODO(maruel): # - File + # - $matching_files + # - use_relative_paths self._commit_git('repo_1', { 'DEPS': """ +vars = { + 'DummyVariable': 'repo', +} deps = { 'src/repo2': 'git://%(host)s/git/repo_2', - 'src/repo2/repo3': '/repo_3', + 'src/repo2/repo3': '/' + Var('DummyVariable') + '_3', } deps_os = { 'mac': { @@ -289,6 +314,21 @@ deps = { 'src/repo2': 'git://%(host)s/git/repo_2@%(hash)s', 'src/repo2/repo_renamed': '/repo_3', } +# I think this is wrong to have the hooks run from the base of the gclient +# checkout. It's maybe a bit too late to change that behavior. +hooks = [ + { + 'pattern': '.', + 'action': ['python', '-c', + 'open(\\'src/hooked1\\', \\'w\\').write(\\'hooked1\\')'], + }, + { + # Should not be run. + 'pattern': 'nonexistent', + 'action': ['python', '-c', + 'open(\\'src/hooked2\\', \\'w\\').write(\\'hooked2\\')'], + }, +] """ % { 'host': '127.0.0.1', 'hash': self.git_hashes['repo_2'][0][0] }, 'origin': "git/repo_1@2\n" }) diff --git a/tests/gclient_smoketest.py b/tests/gclient_smoketest.py index 7f3491f06..bd18aab95 100755 --- a/tests/gclient_smoketest.py +++ b/tests/gclient_smoketest.py @@ -13,6 +13,7 @@ This test assumes GClientSmokeBase.URL_BASE is valid. import logging import os import pprint +import re import shutil import subprocess import sys @@ -106,15 +107,20 @@ class GClientSmokeBase(unittest.TestCase): (stdout, stderr) = process.communicate() return (stdout, stderr, process.returncode) + def checkString(self, expected, result): + if expected != result: + # Strip the begining + while expected and result and expected[0] == result[0]: + expected = expected[1:] + result = result[1:] + # The exception trace makes it hard to read so dump it too. + if '\n' in result: + print result + self.assertEquals(expected, result) + def check(self, expected, results): - def checkString(expected, result): - if expected != result: - while expected and result and expected[0] == result[0]: - expected = expected[1:] - result = result[1:] - self.assertEquals(expected, result) - checkString(expected[0], results[0]) - checkString(expected[1], results[1]) + self.checkString(expected[0], results[0]) + self.checkString(expected[1], results[1]) self.assertEquals(expected[2], results[2]) def assertTree(self, tree): @@ -131,7 +137,7 @@ class GClientSmoke(GClientSmokeBase): def testCommands(self): """This test is to make sure no new command was added.""" result = self.gclient(['help']) - self.assertEquals(3189, len(result[0])) + self.assertEquals(1197, len(result[0])) self.assertEquals(0, len(result[1])) self.assertEquals(0, result[2]) @@ -152,12 +158,13 @@ class GClientSmoke(GClientSmokeBase): class GClientSmokeSVN(GClientSmokeBase): """sync is the most important command. Hence test it more.""" def testSync(self): - """Test pure gclient svn checkout, example of Chromium checkout""" self.gclient(['config', self.svn_base + 'trunk/src/']) # Test unversioned checkout. results = self.gclient(['sync', '--deps', 'mac']) logging.debug(results[0]) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + self.assertEquals(17, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_svn_tree( (join('trunk', 'src'), 'src', FAKE.svn_revs[-1]), @@ -165,13 +172,19 @@ class GClientSmokeSVN(GClientSmokeBase): FAKE.svn_revs[1]), (join('trunk', 'other'), join('src', 'other'), FAKE.svn_revs[2]), ) + tree[join('src', 'hooked1')] = 'hooked1' self.assertTree(tree) + # Manually remove hooked1 before synching to make sure it's not recreated. + os.remove(join(self.root_dir, 'src', 'hooked1')) + # Test incremental versioned sync: sync backward. results = self.gclient(['sync', '--revision', 'src@1', '--deps', 'mac', '--delete_unversioned_trees']) logging.debug(results[0]) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + self.assertEquals(19, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_svn_tree( (join('trunk', 'src'), 'src', FAKE.svn_revs[1]), @@ -186,7 +199,9 @@ class GClientSmokeSVN(GClientSmokeBase): # Test incremental sync: delete-unversioned_trees isn't there. results = self.gclient(['sync', '--deps', 'mac']) logging.debug(results[0]) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + self.assertEquals(21, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_svn_tree( (join('trunk', 'src'), 'src', FAKE.svn_revs[-1]), @@ -199,28 +214,35 @@ class GClientSmokeSVN(GClientSmokeBase): join('src', 'third_party', 'prout'), FAKE.svn_revs[2]), ) + tree[join('src', 'hooked1')] = 'hooked1' self.assertTree(tree) def testRevertAndStatus(self): self.gclient(['config', self.svn_base + 'trunk/src/']) - results = self.gclient(['sync', '--deps', 'mac']) + # Tested in testSync. + self.gclient(['sync', '--deps', 'mac']) write(join(self.root_dir, 'src', 'third_party', 'foo', 'hi'), 'Hey!') results = self.gclient(['status']) out = results[0].splitlines(False) - self.assertEquals(7, len(out)) self.assertEquals(out[0], '') self.assertTrue(out[1].startswith('________ running \'svn status\' in \'')) self.assertEquals(out[2], '? other') - self.assertEquals(out[3], '? third_party/foo') - self.assertEquals(out[4], '') - self.assertTrue(out[5].startswith('________ running \'svn status\' in \'')) - self.assertEquals(out[6], '? hi') + self.assertEquals(out[3], '? hooked1') + self.assertEquals(out[4], '? third_party/foo') + self.assertEquals(out[5], '') + self.assertTrue(out[6].startswith('________ running \'svn status\' in \'')) + self.assertEquals(out[7], '? hi') + self.assertEquals(8, len(out)) self.assertEquals('', results[1]) self.assertEquals(0, results[2]) + # Revert implies --force implies running hooks without looking at pattern + # matching. results = self.gclient(['revert']) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + self.assertEquals(22, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_svn_tree( (join('trunk', 'src'), 'src', FAKE.svn_revs[-1]), @@ -228,26 +250,50 @@ class GClientSmokeSVN(GClientSmokeBase): FAKE.svn_revs[1]), (join('trunk', 'other'), join('src', 'other'), FAKE.svn_revs[2]), ) + tree[join('src', 'hooked1')] = 'hooked1' + tree[join('src', 'hooked2')] = 'hooked2' self.assertTree(tree) results = self.gclient(['status']) out = results[0].splitlines(False) - self.assertEquals(4, len(out)) self.assertEquals(out[0], '') self.assertTrue(out[1].startswith('________ running \'svn status\' in \'')) self.assertEquals(out[2], '? other') - self.assertEquals(out[3], '? third_party/foo') - self.assertEquals('', results[1]) + self.assertEquals(out[3], '? hooked1') + self.assertEquals(out[4], '? hooked2') + self.assertEquals(out[5], '? third_party/foo') + self.assertEquals(6, len(out)) + self.checkString('', results[1]) + self.assertEquals(0, results[2]) + + def testRunHooks(self): + self.gclient(['config', self.svn_base + 'trunk/src/']) + self.gclient(['sync', '--deps', 'mac']) + results = self.gclient(['runhooks']) + out = results[0].splitlines(False) + self.assertEquals(4, len(out)) + self.assertEquals(out[0], '') + self.assertTrue(re.match(r'^________ running \'.*?python -c ' + r'open\(\'src/hooked1\', \'w\'\)\.write\(\'hooked1\'\)\' in \'.*', + out[1])) + self.assertEquals(out[2], '') + # runhooks runs all hooks even if not matching by design. + self.assertTrue(re.match(r'^________ running \'.*?python -c ' + r'open\(\'src/hooked2\', \'w\'\)\.write\(\'hooked2\'\)\' in \'.*', + out[3])) + self.checkString('', results[1]) self.assertEquals(0, results[2]) class GClientSmokeGIT(GClientSmokeBase): - def testSyncGit(self): - """Test pure gclient git checkout, example of Chromium OS checkout""" + def testSync(self): self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) # Test unversioned checkout. results = self.gclient(['sync', '--deps', 'mac']) - logging.debug(results[0]) + out = results[0].splitlines(False) + # TODO(maruel): http://crosbug.com/3582 hooks run even if not matching, must + # add sync parsing to get the list of updated files. + self.assertEquals(13, len(out)) self.assertTrue(results[1].startswith('Switched to a new branch \'')) self.assertEquals(0, results[2]) tree = mangle_git_tree( @@ -255,14 +301,21 @@ class GClientSmokeGIT(GClientSmokeBase): (join('src', 'repo2'), FAKE.git_hashes['repo_2'][0][1]), (join('src', 'repo2', 'repo_renamed'), FAKE.git_hashes['repo_3'][1][1]), ) + tree[join('src', 'hooked1')] = 'hooked1' + tree[join('src', 'hooked2')] = 'hooked2' self.assertTree(tree) + # Manually remove hooked1 before synching to make sure it's not recreated. + os.remove(join(self.root_dir, 'src', 'hooked1')) + # Test incremental versioned sync: sync backward. results = self.gclient(['sync', '--revision', 'src@' + FAKE.git_hashes['repo_1'][0][0], '--deps', 'mac', '--delete_unversioned_trees']) logging.debug(results[0]) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + self.assertEquals(20, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_git_tree( ('src', FAKE.git_hashes['repo_1'][0][1]), @@ -270,11 +323,14 @@ class GClientSmokeGIT(GClientSmokeBase): (join('src', 'repo2', 'repo3'), FAKE.git_hashes['repo_3'][1][1]), (join('src', 'repo4'), FAKE.git_hashes['repo_4'][1][1]), ) + tree[join('src', 'hooked2')] = 'hooked2' self.assertTree(tree) # Test incremental sync: delete-unversioned_trees isn't there. results = self.gclient(['sync', '--deps', 'mac']) logging.debug(results[0]) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + self.assertEquals(25, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_git_tree( ('src', FAKE.git_hashes['repo_1'][1][1]), @@ -283,42 +339,66 @@ class GClientSmokeGIT(GClientSmokeBase): (join('src', 'repo2', 'repo_renamed'), FAKE.git_hashes['repo_3'][1][1]), (join('src', 'repo4'), FAKE.git_hashes['repo_4'][1][1]), ) + tree[join('src', 'hooked1')] = 'hooked1' + tree[join('src', 'hooked2')] = 'hooked2' self.assertTree(tree) def testRevertAndStatus(self): """TODO(maruel): Remove this line once this test is fixed.""" self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) - results = self.gclient(['sync', '--deps', 'mac']) + # Tested in testSync. + self.gclient(['sync', '--deps', 'mac']) write(join(self.root_dir, 'src', 'repo2', 'hi'), 'Hey!') results = self.gclient(['status']) out = results[0].splitlines(False) - # TODO(maruel): THIS IS WRONG. + # TODO(maruel): http://crosbug.com/3584 It should output the unversioned + # files. self.assertEquals(0, len(out)) + # Revert implies --force implies running hooks without looking at pattern + # matching. results = self.gclient(['revert']) - self.assertEquals('', results[1]) + out = results[0].splitlines(False) + # TODO(maruel): http://crosbug.com/3583 It just runs the hooks right now. + self.assertEquals(7, len(out)) + self.checkString('', results[1]) self.assertEquals(0, results[2]) tree = mangle_git_tree( ('src', FAKE.git_hashes['repo_1'][1][1]), (join('src', 'repo2'), FAKE.git_hashes['repo_2'][0][1]), (join('src', 'repo2', 'repo_renamed'), FAKE.git_hashes['repo_3'][1][1]), ) - # TODO(maruel): THIS IS WRONG. + # TODO(maruel): http://crosbug.com/3583 This file should have been removed. tree[join('src', 'repo2', 'hi')] = 'Hey!' + tree[join('src', 'hooked1')] = 'hooked1' + tree[join('src', 'hooked2')] = 'hooked2' self.assertTree(tree) results = self.gclient(['status']) out = results[0].splitlines(False) - # TODO(maruel): THIS IS WRONG. + # TODO(maruel): http://crosbug.com/3584 It should output the unversioned + # files. self.assertEquals(0, len(out)) - -class GClientSmokeRevInfo(GClientSmokeBase): - """revert is the second most important command. Hence test it more.""" - def setUp(self): - GClientSmokeBase.setUp(self) - self.gclient(['config', self.URL_BASE]) + def testRunHooks(self): + self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) + self.gclient(['sync', '--deps', 'mac']) + results = self.gclient(['runhooks']) + logging.debug(results[0]) + out = results[0].splitlines(False) + self.assertEquals(4, len(out)) + self.assertEquals(out[0], '') + self.assertTrue(re.match(r'^________ running \'.*?python -c ' + r'open\(\'src/hooked1\', \'w\'\)\.write\(\'hooked1\'\)\' in \'.*', + out[1])) + self.assertEquals(out[2], '') + # runhooks runs all hooks even if not matching by design. + self.assertTrue(re.match(r'^________ running \'.*?python -c ' + r'open\(\'src/hooked2\', \'w\'\)\.write\(\'hooked2\'\)\' in \'.*', + out[3])) + self.checkString('', results[1]) + self.assertEquals(0, results[2]) if __name__ == '__main__': diff --git a/tests/gclient_test.py b/tests/gclient_test.py deleted file mode 100755 index c81a9de57..000000000 --- a/tests/gclient_test.py +++ /dev/null @@ -1,1273 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2010 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Unit tests for gclient.py.""" - -# Fixes include path. -from super_mox import mox, SuperMoxTestBase - -import gclient - - -class BaseTestCase(SuperMoxTestBase): - # Like unittest's assertRaises, but checks for Gclient.Error. - def assertRaisesError(self, msg, fn, *args, **kwargs): - try: - fn(*args, **kwargs) - except gclient.gclient_utils.Error, e: - self.assertEquals(e.args[0], msg) - else: - self.fail('%s not raised' % msg) - - -class GClientBaseTestCase(BaseTestCase): - def Options(self, *args, **kwargs): - return self.OptionsObject(self, *args, **kwargs) - - def setUp(self): - BaseTestCase.setUp(self) - # These are not tested. - self.mox.StubOutWithMock(gclient.gclient_utils, 'FileRead') - self.mox.StubOutWithMock(gclient.gclient_utils, 'FileWrite') - self.mox.StubOutWithMock(gclient.gclient_utils, 'SubprocessCall') - self.mox.StubOutWithMock(gclient.gclient_utils, 'RemoveDirectory') - # Mock them to be sure nothing bad happens. - self.mox.StubOutWithMock(gclient.gclient_scm.scm.SVN, 'Capture') - self.mox.StubOutWithMock(gclient.gclient_scm.scm.SVN, 'CaptureInfo') - self.mox.StubOutWithMock(gclient.gclient_scm.scm.SVN, 'CaptureStatus') - self.mox.StubOutWithMock(gclient.gclient_scm.scm.SVN, 'Run') - self.mox.StubOutWithMock(gclient.gclient_scm.scm.SVN, 'RunAndGetFileList') - self._gclient_gclient = gclient.GClient - gclient.GClient = self.mox.CreateMockAnything() - gclient.GClient.DEPS_FILE = self._gclient_gclient.DEPS_FILE - gclient.GClient.DEFAULT_CLIENT_FILE_TEXT = ( - self._gclient_gclient.DEFAULT_CLIENT_FILE_TEXT) - self._scm_wrapper = gclient.gclient_scm.CreateSCM - gclient.gclient_scm.CreateSCM = self.mox.CreateMockAnything() - - def tearDown(self): - gclient.GClient = self._gclient_gclient - gclient.gclient_scm.CreateSCM = self._scm_wrapper - BaseTestCase.tearDown(self) - - -class GclientTestCase(GClientBaseTestCase): - class OptionsObject(object): - def __init__(self, test_case, verbose=0, spec=None, - config_filename='a_file_name', - entries_filename='a_entry_file_name', - force=False, nohooks=False): - self.verbose = verbose - self.config_filename = config_filename - self.entries_filename = entries_filename - self.spec = spec - self.name = None - self.force = force - self.nohooks = nohooks - self.revisions = [] - self.manually_grab_svn_rev = True - self.deps_os = None - self.head = False - - def setUp(self): - GClientBaseTestCase.setUp(self) - self.args = self.Args() - self.root_dir = self.Dir() - self.url = self.Url() - - -class GClientCommandsTestCase(GClientBaseTestCase): - def testCommands(self): - known_commands = [gclient.CMDcleanup, gclient.CMDconfig, gclient.CMDdiff, - gclient.CMDexport, gclient.CMDhelp, gclient.CMDpack, - gclient.CMDrevert, gclient.CMDrevinfo, - gclient.CMDrunhooks, gclient.CMDstatus, gclient.CMDsync, - gclient.CMDupdate] - cmds = [getattr(gclient, x) for x in dir(gclient) if x.startswith('CMD')] - self.assertEquals(len(known_commands), len(cmds)) - for v in cmds: - # If it fails, you need to add a test case for the new command. - self.assert_(v in known_commands) - self.mox.ReplayAll() - -class TestCMDconfig(GclientTestCase): - def testMissingArgument(self): - exception_msg = "required argument missing; see 'gclient help config'" - - self.mox.ReplayAll() - self.assertRaisesError(exception_msg, gclient.CMDconfig, None, - self.Options(), ()) - - def testExistingClientFile(self): - options = self.Options() - exception_msg = ('%s file already exists in the current directory' % - options.config_filename) - gclient.os.path.exists(options.config_filename).AndReturn(True) - - self.mox.ReplayAll() - self.assertRaisesError(exception_msg, gclient.CMDconfig, None, options, - (1,)) - - def testFromText(self): - options = self.Options(spec='config_source_content') - gclient.os.path.exists(options.config_filename).AndReturn(False) - gclient.GClient('.', options).AndReturn(gclient.GClient) - gclient.GClient.SetConfig(options.spec) - gclient.GClient.SaveConfig() - - self.mox.ReplayAll() - gclient.CMDconfig(None, options, (1,),) - - def testCreateClientFile(self): - options = self.Options() - gclient.os.path.exists(options.config_filename).AndReturn(False) - gclient.GClient('.', options).AndReturn(gclient.GClient) - gclient.GClient.SetDefaultConfig('the_name', 'http://svn/url/the_name', - 'other') - gclient.GClient.SaveConfig() - - self.mox.ReplayAll() - gclient.CMDconfig(None, options, - ('http://svn/url/the_name', 'other', 'args', 'ignored')) - - -class GenericCommandTestCase(GclientTestCase): - def ReturnValue(self, command, return_value): - options = self.Options() - gclient.GClient.LoadCurrentConfig(options).AndReturn(gclient.GClient) - gclient.GClient.RunOnDeps(command, self.args).AndReturn(return_value) - - self.mox.ReplayAll() - function = getattr(gclient, 'CMD' + command) - result = function(None, options, self.args) - self.assertEquals(result, return_value) - - def BadClient(self, command): - options = self.Options() - gclient.GClient.LoadCurrentConfig(options).AndReturn(None) - - self.mox.ReplayAll() - function = getattr(gclient, 'CMD' + command) - self.assertRaisesError( - "client not configured; see 'gclient config'", - function, None, options, self.args) - - def Verbose(self, command): - options = self.Options(verbose=True) - gclient.GClient.LoadCurrentConfig(options).AndReturn(gclient.GClient) - text = "# Dummy content\nclient = 'my client'" - gclient.GClient.ConfigContent().AndReturn(text) - print(text) - gclient.GClient.RunOnDeps(command, self.args).AndReturn(0) - - self.mox.ReplayAll() - function = getattr(gclient, 'CMD' + command) - result = function(None, options, self.args) - self.assertEquals(result, 0) - - -class TestCMDcleanup(GenericCommandTestCase): - def testGoodClient(self): - self.ReturnValue('cleanup', 0) - def testError(self): - self.ReturnValue('cleanup', 42) - def testBadClient(self): - self.BadClient('cleanup') - - -class TestCMDstatus(GenericCommandTestCase): - def testGoodClient(self): - self.ReturnValue('status', 0) - def testError(self): - self.ReturnValue('status', 42) - def testBadClient(self): - self.BadClient('status') - - -class TestCMDrunhooks(GenericCommandTestCase): - def Options(self, verbose=False, *args, **kwargs): - return self.OptionsObject(self, verbose=verbose, *args, **kwargs) - - def testGoodClient(self): - self.ReturnValue('runhooks', 0) - def testError(self): - self.ReturnValue('runhooks', 42) - def testBadClient(self): - self.BadClient('runhooks') - - -class TestCMDupdate(GenericCommandTestCase): - def ReturnValue(self, command, return_value): - options = self.Options() - gclient.GClient.LoadCurrentConfig(options).AndReturn(gclient.GClient) - gclient.GClient.GetVar("solutions") - gclient.GClient.RunOnDeps(command, self.args).AndReturn(return_value) - - self.mox.ReplayAll() - function = getattr(gclient, 'CMD' + command) - result = function(None, options, self.args) - self.assertEquals(result, return_value) - - def Verbose(self, command): - options = self.Options(verbose=True) - gclient.GClient.LoadCurrentConfig(options).AndReturn(gclient.GClient) - gclient.GClient.GetVar("solutions") - text = "# Dummy content\nclient = 'my client'" - gclient.GClient.ConfigContent().AndReturn(text) - print(text) - gclient.GClient.RunOnDeps(command, self.args).AndReturn(0) - - self.mox.ReplayAll() - function = getattr(gclient, 'CMD' + command) - result = function(None, options, self.args) - self.assertEquals(result, 0) - - def Options(self, verbose=False, *args, **kwargs): - return self.OptionsObject(self, verbose=verbose, *args, **kwargs) - - def testBasic(self): - self.ReturnValue('update', 0) - def testError(self): - self.ReturnValue('update', 42) - def testBadClient(self): - self.BadClient('update') - def testVerbose(self): - self.Verbose('update') - - -class TestCMDdiff(GenericCommandTestCase): - def Options(self, *args, **kwargs): - return self.OptionsObject(self, *args, **kwargs) - - def testBasic(self): - self.ReturnValue('diff', 0) - def testError(self): - self.ReturnValue('diff', 42) - def testBadClient(self): - self.BadClient('diff') - def testVerbose(self): - self.Verbose('diff') - - -class TestCMDexport(GenericCommandTestCase): - def testBasic(self): - self.args = ['dir'] - self.ReturnValue('export', 0) - def testError(self): - self.args = ['dir'] - self.ReturnValue('export', 42) - def testBadClient(self): - self.args = ['dir'] - self.BadClient('export') - - -class TestCMDpack(GenericCommandTestCase): - def Options(self, *args, **kwargs): - return self.OptionsObject(self, *args, **kwargs) - - def testBasic(self): - self.ReturnValue('pack', 0) - def testError(self): - self.ReturnValue('pack', 42) - def testBadClient(self): - self.BadClient('pack') - - -class TestCMDrevert(GenericCommandTestCase): - def testBasic(self): - self.ReturnValue('revert', 0) - def testError(self): - self.ReturnValue('revert', 42) - def testBadClient(self): - self.BadClient('revert') - - -class GClientClassTestCase(GclientTestCase): - def testDir(self): - members = [ - 'ConfigContent', 'DEFAULT_CLIENT_FILE_TEXT', - 'DEFAULT_SNAPSHOT_FILE_TEXT', 'DEFAULT_SNAPSHOT_SOLUTION_TEXT', - 'DEPS_FILE', 'FileImpl', 'FromImpl', 'GetVar', 'LoadCurrentConfig', - 'PrintRevInfo', 'RunOnDeps', 'SaveConfig', 'SetConfig', - 'SetDefaultConfig', - 'deps_os_choices', 'supported_commands', - ] - - # If you add a member, be sure to add the relevant test! - self.compareMembers(self._gclient_gclient('root_dir', 'options'), members) - - def testSetConfig_ConfigContent_GetVar_SaveConfig_SetDefaultConfig(self): - options = self.Options() - text = "# Dummy content\nclient = 'my client'" - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.config_filename), - text) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(text) - self.assertEqual(client.ConfigContent(), text) - self.assertEqual(client.GetVar('client'), 'my client') - self.assertEqual(client.GetVar('foo'), None) - client.SaveConfig() - - solution_name = 'solution name' - solution_url = 'solution url' - safesync_url = 'safesync url' - default_text = gclient.GClient.DEFAULT_CLIENT_FILE_TEXT % { - 'solution_name' : solution_name, - 'solution_url' : solution_url, - 'safesync_url' : safesync_url - } - client.SetDefaultConfig(solution_name, solution_url, safesync_url) - self.assertEqual(client.ConfigContent(), default_text) - solutions = [{ - 'name': solution_name, - 'url': solution_url, - 'custom_deps': {}, - 'safesync_url': safesync_url - }] - self.assertEqual(client.GetVar('solutions'), solutions) - self.assertEqual(client.GetVar('foo'), None) - - def testLoadCurrentConfig(self): - options = self.Options() - gclient.os.path.realpath(self.root_dir).AndReturn(self.root_dir) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.config_filename) - ).AndReturn(True) - gclient.GClient(self.root_dir, options).AndReturn(gclient.GClient) - gclient.GClient._LoadConfig() - - self.mox.ReplayAll() - client = self._gclient_gclient.LoadCurrentConfig(options, self.root_dir) - - def testRunOnDepsNoDeps(self): - solution_name = 'testRunOnDepsNoDeps_solution_name' - gclient_config = ( - "solutions = [ {\n" - " 'name': '%s',\n" - " 'url': '%s',\n" - " 'custom_deps': {},\n" - "} ]\n" - ) % (solution_name, self.url) - - # pprint.pformat() is non-deterministic in this case!! - entries_content = ( - "entries = \\\n" - "{ '%s': '%s'}\n" - ) % (solution_name, self.url) - - options = self.Options() - - checkout_path = gclient.os.path.join(self.root_dir, solution_name) - gclient.os.path.exists(gclient.os.path.join(checkout_path, '.git') - ).AndReturn(False) - # Expect a check for the entries file and we say there is not one. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - - # An scm will be requested for the solution. - scm_wrapper_sol = self.mox.CreateMockAnything() - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, solution_name - ).AndReturn(scm_wrapper_sol) - # Then an update will be performed. - scm_wrapper_sol.RunCommand('update', options, self.args, []) - # Then an attempt will be made to read its DEPS file. - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, solution_name, - gclient.GClient.DEPS_FILE) - ).AndRaise(IOError(2, 'No DEPS file')) - - # After everything is done, an attempt is made to write an entries - # file. - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsRelativePaths(self): - solution_name = 'testRunOnDepsRelativePaths_solution_name' - gclient_config = ( - "solutions = [ {\n" - " 'name': '%s',\n" - " 'url': '%s',\n" - " 'custom_deps': {},\n" - "} ]\n" - ) % (solution_name, self.url) - - deps = ( - "use_relative_paths = True\n" - "deps = {\n" - " 'src/t': 'svn://scm.t/trunk',\n" - "}\n") - entry_path = gclient.os.path.join(solution_name, 'src', 't' - ).replace('\\', '\\\\') - entries_content = ( - "entries = \\\n" - "{ '%s': '%s',\n" - " '%s': 'svn://scm.t/trunk'}\n" - ) % (solution_name, self.url, entry_path) - - scm_wrapper_sol = self.mox.CreateMockAnything() - scm_wrapper_t = self.mox.CreateMockAnything() - - options = self.Options() - - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, solution_name, 'src', 't', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, solution_name, '.git') - ).AndReturn(False) - # Expect a check for the entries file and we say there is not one. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - - # An scm will be requested for the solution. - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, solution_name - ).AndReturn(scm_wrapper_sol) - # Then an update will be performed. - scm_wrapper_sol.RunCommand('update', options, self.args, []) - # Then an attempt will be made to read its DEPS file. - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, solution_name, - gclient.GClient.DEPS_FILE) - ).AndReturn(deps) - - # Next we expect an scm to be request for dep src/t but it should - # use the url specified in deps and the relative path should now - # be relative to the DEPS file. - gclient.gclient_scm.CreateSCM( - 'svn://scm.t/trunk', - self.root_dir, - gclient.os.path.join(solution_name, "src", "t") - ).AndReturn(scm_wrapper_t) - scm_wrapper_t.RunCommand('update', options, self.args, []) - - # After everything is done, an attempt is made to write an entries - # file. - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsCustomDeps(self): - solution_name = 'testRunOnDepsCustomDeps_solution_name' - gclient_config = ( - "solutions = [ {\n" - " 'name': '%s',\n" - " 'url': '%s',\n" - " 'custom_deps': {\n" - " 'src/b': None,\n" - " 'src/n': 'svn://custom.n/trunk',\n" - " 'src/t': 'svn://custom.t/trunk',\n" - " }\n} ]\n" - ) % (solution_name, self.url) - - deps = ( - "deps = {\n" - " 'src/b': 'svn://original.b/trunk',\n" - " 'src/t': 'svn://original.t/trunk',\n" - "}\n" - ) - - entries_content = ( - "entries = \\\n" - "{ 'src/n': 'svn://custom.n/trunk',\n" - " 'src/t': 'svn://custom.t/trunk',\n" - " '%s': '%s'}\n" - ) % (solution_name, self.url) - - scm_wrapper_sol = self.mox.CreateMockAnything() - scm_wrapper_t = self.mox.CreateMockAnything() - scm_wrapper_n = self.mox.CreateMockAnything() - - options = self.Options() - - checkout_path = gclient.os.path.join(self.root_dir, solution_name) - gclient.os.path.exists( - gclient.os.path.join(checkout_path, '.git')).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'src/n', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'src/t', '.git') - ).AndReturn(False) - - # Expect a check for the entries file and we say there is not one. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - - # An scm will be requested for the solution. - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, solution_name - ).AndReturn(scm_wrapper_sol) - # Then an update will be performed. - scm_wrapper_sol.RunCommand('update', options, self.args, []) - # Then an attempt will be made to read its DEPS file. - gclient.gclient_utils.FileRead( - gclient.os.path.join(checkout_path, gclient.GClient.DEPS_FILE) - ).AndReturn(deps) - - # Next we expect an scm to be request for dep src/n even though it does not - # exist in the DEPS file. - gclient.gclient_scm.CreateSCM('svn://custom.n/trunk', - self.root_dir, - "src/n").AndReturn(scm_wrapper_n) - - # Next we expect an scm to be request for dep src/t but it should - # use the url specified in custom_deps. - gclient.gclient_scm.CreateSCM('svn://custom.t/trunk', - self.root_dir, - "src/t").AndReturn(scm_wrapper_t) - - scm_wrapper_n.RunCommand('update', options, self.args, []) - scm_wrapper_t.RunCommand('update', options, self.args, []) - - # NOTE: the dep src/b should not create an scm at all. - - # After everything is done, an attempt is made to write an entries - # file. - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - # Regression test for Issue #11. - # http://code.google.com/p/gclient/issues/detail?id=11 - def testRunOnDepsSharedDependency(self): - name_a = 'testRunOnDepsSharedDependency_a' - name_b = 'testRunOnDepsSharedDependency_b' - - url_a = self.url + '/a' - url_b = self.url + '/b' - - # config declares two solutions and each has a dependency to place - # http://svn.t/trunk at src/t. - gclient_config = ( - "solutions = [ {\n" - " 'name': '%s',\n" - " 'url': '%s',\n" - " 'custom_deps': {},\n" - "}, {\n" - " 'name': '%s',\n" - " 'url': '%s',\n" - " 'custom_deps': {},\n" - "}\n]\n") % (name_a, url_a, name_b, url_b) - - deps_b = deps_a = ( - "deps = {\n" - " 'src/t' : 'http://svn.t/trunk',\n" - "}\n") - - entries_content = ( - "entries = \\\n" - "{ 'src/t': 'http://svn.t/trunk',\n" - " '%s': '%s',\n" - " '%s': '%s'}\n" - ) % (name_a, url_a, name_b, url_b) - - scm_wrapper_a = self.mox.CreateMockAnything() - scm_wrapper_b = self.mox.CreateMockAnything() - scm_wrapper_dep = self.mox.CreateMockAnything() - - options = self.Options() - - gclient.os.path.exists(gclient.os.path.join(self.root_dir, name_a, '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, name_b, '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'src/t', '.git') - ).AndReturn(False) - - # Expect a check for the entries file and we say there is not one. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - - # An scm will be requested for the first solution. - gclient.gclient_scm.CreateSCM(url_a, self.root_dir, name_a).AndReturn( - scm_wrapper_a) - # Then an attempt will be made to read it's DEPS file. - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name_a, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_a) - # Then an update will be performed. - scm_wrapper_a.RunCommand('update', options, self.args, []) - - # An scm will be requested for the second solution. - gclient.gclient_scm.CreateSCM(url_b, self.root_dir, name_b).AndReturn( - scm_wrapper_b) - # Then an attempt will be made to read its DEPS file. - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name_b, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_b) - # Then an update will be performed. - scm_wrapper_b.RunCommand('update', options, self.args, []) - - # Finally, an scm is requested for the shared dep. - gclient.gclient_scm.CreateSCM('http://svn.t/trunk', self.root_dir, 'src/t' - ).AndReturn(scm_wrapper_dep) - # And an update is run on it. - scm_wrapper_dep.RunCommand('update', options, self.args, []) - - # After everything is done, an attempt is made to write an entries file. - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsSuccess(self): - # Fake .gclient file. - name = 'testRunOnDepsSuccess_solution_name' - gclient_config = """solutions = [ { - 'name': '%s', - 'url': '%s', - 'custom_deps': {}, -}, ]""" % (name, self.url) - - # pprint.pformat() is non-deterministic in this case!! - entries_content = ( - "entries = \\\n" - "{ '%s': '%s'}\n" - ) % (name, self.url) - - options = self.Options() - gclient.os.path.exists(gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn("Boo = 'a'") - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsRevisions(self): - def OptIsRev(options, rev): - if not options.revision == str(rev): - print("options.revision = %s" % options.revision) - return options.revision == str(rev) - def OptIsRevNone(options): - if options.revision: - print("options.revision = %s" % options.revision) - return options.revision == None - def OptIsRev42(options): - return OptIsRev(options, 42) - def OptIsRev123(options): - return OptIsRev(options, 123) - def OptIsRev333(options): - return OptIsRev(options, 333) - - # Fake .gclient file. - gclient_config = """solutions = [ { - 'name': 'src', - 'url': '%s', - 'custom_deps': {}, -}, ]""" % self.url - # Fake DEPS file. - deps_content = """deps = { - 'src/breakpad/bar': 'http://google-breakpad.googlecode.com/svn/trunk/src@285', - 'foo/third_party/WebKit': '/trunk/deps/third_party/WebKit', - 'src/third_party/cygwin': '/trunk/deps/third_party/cygwin@3248', -} -deps_os = { - 'win': { - 'src/foosad/asdf': 'svn://random_server:123/asd/python_24@5580', - }, - 'mac': { - 'src/third_party/python_24': 'svn://random_server:123/trunk/python_24@5580', - }, -}""" - - cygwin_path = 'dummy path cygwin' - webkit_path = 'dummy path webkit' - - entries_content = ( - "entries = \\\n" - "{ 'foo/third_party/WebKit': '%s',\n" - " 'src': '%s',\n" - " 'src/breakpad/bar':" - " 'http://google-breakpad.googlecode.com/svn/trunk/src@285',\n" - " 'src/third_party/cygwin': '%s',\n" - " 'src/third_party/python_24':" - " 'svn://random_server:123/trunk/python_24@5580'}\n" - ) % (webkit_path, self.url, cygwin_path) - - scm_wrapper_bleh = self.mox.CreateMockAnything() - scm_wrapper_src = self.mox.CreateMockAnything() - scm_wrapper_src2 = self.mox.CreateMockAnything() - scm_wrapper_webkit = self.mox.CreateMockAnything() - scm_wrapper_breakpad = self.mox.CreateMockAnything() - scm_wrapper_cygwin = self.mox.CreateMockAnything() - scm_wrapper_python = self.mox.CreateMockAnything() - options = self.Options() - options.revisions = [ 'src@123', 'foo/third_party/WebKit@42', - 'src/third_party/cygwin@333' ] - options.deps_os = 'mac' - # Also, pymox doesn't verify the order of function calling w.r.t. different - # mock objects. Pretty lame. So reorder as we wish to make it clearer. - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, 'src', gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'src', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, 'foo/third_party/WebKit', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, 'src/third_party/cygwin', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, 'src/third_party/python_24', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, 'src/breakpad/bar', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, 'src').AndReturn( - scm_wrapper_src) - scm_wrapper_src.RunCommand('update', mox.Func(OptIsRev123), self.args, []) - - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, - None).AndReturn(scm_wrapper_src2) - scm_wrapper_src2.FullUrlForRelativeUrl('/trunk/deps/third_party/cygwin@3248' - ).AndReturn(cygwin_path) - - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, - None).AndReturn(scm_wrapper_src2) - scm_wrapper_src2.FullUrlForRelativeUrl('/trunk/deps/third_party/WebKit' - ).AndReturn(webkit_path) - - gclient.gclient_scm.CreateSCM( - webkit_path, self.root_dir, 'foo/third_party/WebKit' - ).AndReturn(scm_wrapper_webkit) - scm_wrapper_webkit.RunCommand('update', mox.Func(OptIsRev42), self.args, []) - - gclient.gclient_scm.CreateSCM( - 'http://google-breakpad.googlecode.com/svn/trunk/src@285', - self.root_dir, 'src/breakpad/bar').AndReturn(scm_wrapper_breakpad) - scm_wrapper_breakpad.RunCommand('update', mox.Func(OptIsRevNone), - self.args, []) - - gclient.gclient_scm.CreateSCM( - cygwin_path, self.root_dir, 'src/third_party/cygwin' - ).AndReturn(scm_wrapper_cygwin) - scm_wrapper_cygwin.RunCommand('update', mox.Func(OptIsRev333), self.args, - []) - - gclient.gclient_scm.CreateSCM( - 'svn://random_server:123/trunk/python_24@5580', - self.root_dir, - 'src/third_party/python_24' - ).AndReturn(scm_wrapper_python) - scm_wrapper_python.RunCommand('update', mox.Func(OptIsRevNone), self.args, - []) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsConflictingRevisions(self): - # Fake .gclient file. - name = 'testRunOnDepsConflictingRevisions_solution_name' - gclient_config = """solutions = [ { - 'name': '%s', - 'url': '%s', - 'custom_deps': {}, - 'custom_vars': {}, -}, ]""" % (name, self.url) - # Fake DEPS file. - deps_content = """deps = { - 'foo/third_party/WebKit': '/trunk/deps/third_party/WebKit', -}""" - - options = self.Options() - options.revisions = [ 'foo/third_party/WebKit@42', - 'foo/third_party/WebKit@43' ] - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - exception = "Conflicting revision numbers specified." - try: - client.RunOnDeps('update', self.args) - except gclient.gclient_utils.Error, e: - self.assertEquals(e.args[0], exception) - else: - self.fail('%s not raised' % exception) - - def testRunOnDepsSuccessVars(self): - # Fake .gclient file. - name = 'testRunOnDepsSuccessVars_solution_name' - gclient_config = """solutions = [ { - 'name': '%s', - 'url': '%s', - 'custom_deps': {}, - 'custom_vars': {}, -}, ]""" % (name, self.url) - # Fake DEPS file. - deps_content = """vars = { - 'webkit': '/trunk/bar/', -} -deps = { - 'foo/third_party/WebKit': Var('webkit') + 'WebKit', -}""" - - webkit_path = 'dummy path webkit' - - entries_content = ( - "entries = \\\n" - "{ 'foo/third_party/WebKit': '%s',\n" - " '%s': '%s'}\n" - ) % (webkit_path, name, self.url) - - scm_wrapper_webkit = self.mox.CreateMockAnything() - scm_wrapper_src = self.mox.CreateMockAnything() - - options = self.Options() - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, - gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, 'foo/third_party/WebKit', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, None - ).AndReturn(scm_wrapper_src) - scm_wrapper_src.FullUrlForRelativeUrl('/trunk/bar/WebKit' - ).AndReturn(webkit_path) - - gclient.gclient_scm.CreateSCM( - webkit_path, self.root_dir, 'foo/third_party/WebKit' - ).AndReturn(gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsSuccessCustomVars(self): - # Fake .gclient file. - name = 'testRunOnDepsSuccessCustomVars_solution_name' - gclient_config = """solutions = [ { - 'name': '%s', - 'url': '%s', - 'custom_deps': {}, - 'custom_vars': {'webkit': '/trunk/bar_custom/'}, -}, ]""" % (name, self.url) - # Fake DEPS file. - deps_content = """vars = { - 'webkit': '/trunk/bar/', -} -deps = { - 'foo/third_party/WebKit': Var('webkit') + 'WebKit', -}""" - - webkit_path = 'dummy path webkit' - - entries_content = ( - "entries = \\\n" - "{ 'foo/third_party/WebKit': '%s',\n" - " '%s': '%s'}\n" - ) % (webkit_path, name, self.url) - - scm_wrapper_webkit = self.mox.CreateMockAnything() - scm_wrapper_src = self.mox.CreateMockAnything() - - options = self.Options() - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - entries_content) - - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, 'foo/third_party/WebKit', '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, - None).AndReturn(scm_wrapper_src) - scm_wrapper_src.FullUrlForRelativeUrl('/trunk/bar_custom/WebKit' - ).AndReturn(webkit_path) - - gclient.gclient_scm.CreateSCM(webkit_path, self.root_dir, - 'foo/third_party/WebKit').AndReturn(gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testRunOnDepsFailureVars(self): - # Fake .gclient file. - name = 'testRunOnDepsFailureVars_solution_name' - gclient_config = """solutions = [ { - 'name': '%s', - 'url': '%s', - 'custom_deps': {}, - 'custom_vars': {}, -}, ]""" % (name, self.url) - # Fake DEPS file. - deps_content = """deps = { - 'foo/third_party/WebKit': Var('webkit') + 'WebKit', -}""" - - options = self.Options() - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - exception = "Var is not defined: webkit" - try: - client.RunOnDeps('update', self.args) - except gclient.gclient_utils.Error, e: - self.assertEquals(e.args[0], exception) - else: - self.fail('%s not raised' % exception) - - def testRunOnDepsFailureInvalidCommand(self): - options = self.Options() - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - exception = "'foo' is an unsupported command" - self.assertRaisesError(exception, self._gclient_gclient.RunOnDeps, client, - 'foo', self.args) - - def testRunOnDepsFailureEmpty(self): - options = self.Options() - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - exception = "No solution specified" - self.assertRaisesError(exception, self._gclient_gclient.RunOnDeps, client, - 'update', self.args) - - def testFromImplOne(self): - base_url = 'svn://base@123' - deps_content = ( - "deps = {\n" - " 'base': '%s',\n" - " 'main': From('base'),\n" - "}\n" % base_url - ) - main_url = 'svn://main@456' - base_deps_content = ( - "deps = {\n" - " 'main': '%s',\n" - "}\n" % main_url - ) - # Fake .gclient file. - name = 'testFromImplOne_solution_name' - gclient_config = ( - "solutions = [ {\n" - "'name': '%s',\n" - "'url': '%s',\n" - "'custom_deps': {},\n" - "}, ]" % (name, self.url)) - - options = self.Options() - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'main', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'base', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - - # base gets updated. - gclient.gclient_scm.CreateSCM(base_url, self.root_dir, 'base').AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, 'base', gclient.GClient.DEPS_FILE) - ).AndReturn(base_deps_content) - - # main gets updated. - gclient.gclient_scm.CreateSCM(main_url, self.root_dir, 'main').AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - # Process is done and will write an .gclient_entries. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - mox.IgnoreArg()) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testFromImplTwo(self): - base_url = 'svn://base@123' - deps_content = ( - "deps = {\n" - " 'base': '%s',\n" - " 'main': From('base', 'src/main'),\n" - "}\n" % base_url - ) - main_url = 'svn://main@456' - base_deps_content = ( - "deps = {\n" - " 'src/main': '%s',\n" - "}\n" % main_url - ) - # Fake .gclient file. - name = 'testFromImplTwo_solution_name' - gclient_config = ( - "solutions = [ {\n" - "'name': '%s',\n" - "'url': '%s',\n" - "'custom_deps': {},\n" - "}, ]" % (name, self.url)) - - options = self.Options() - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'main', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'base', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - - # base gets updated. - gclient.gclient_scm.CreateSCM(base_url, self.root_dir, 'base').AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, 'base', gclient.GClient.DEPS_FILE) - ).AndReturn(base_deps_content) - - # main gets updated. - gclient.gclient_scm.CreateSCM(main_url, self.root_dir, 'main').AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - # Process is done and will write an .gclient_entries. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - mox.IgnoreArg()) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testFromImplTwoRelatvie(self): - base_url = 'svn://base@123' - deps_content = ( - "deps = {\n" - " 'base': '%s',\n" - " 'main': From('base', 'src/main'),\n" - "}\n" % base_url - ) - main_url = '/relative@456' - base_deps_content = ( - "deps = {\n" - " 'src/main': '%s',\n" - "}\n" % main_url - ) - # Fake .gclient file. - name = 'testFromImplTwo_solution_name' - gclient_config = ( - "solutions = [ {\n" - "'name': '%s',\n" - "'url': '%s',\n" - "'custom_deps': {},\n" - "}, ]" % (name, self.url)) - - options = self.Options() - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'main', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, 'base', '.git') - ).AndReturn(False) - gclient.os.path.exists(gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - - # base gets updated. - gclient.gclient_scm.CreateSCM(base_url, self.root_dir, 'base').AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, 'base', gclient.GClient.DEPS_FILE) - ).AndReturn(base_deps_content) - - # main gets updated after resolving the relative url. - gclient.gclient_scm.CreateSCM(base_url, self.root_dir, None).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.FullUrlForRelativeUrl(main_url - ).AndReturn('svn://base' + main_url) - gclient.gclient_scm.CreateSCM('svn://base' + main_url, self.root_dir, - 'main').AndReturn(gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - - # Process is done and will write an .gclient_entries. - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - mox.IgnoreArg()) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def testFileImpl(self): - # Fake .gclient file. - name = "testFileImpl" - gclient_config = ( - "solutions = [ { 'name': '%s'," - "'url': '%s', } ]" % (name, self.url) - ) - # Fake DEPS file. - target = "chromium_deps" - deps_content = ( - "deps = {" - " '%s': File('%s/DEPS') }" % (target, self.url) - ) - - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, name).AndReturn( - gclient.gclient_scm.CreateSCM) - options = self.Options() - gclient.gclient_scm.CreateSCM.RunCommand('update', options, self.args, []) - gclient.gclient_utils.FileRead( - gclient.os.path.join(self.root_dir, name, gclient.GClient.DEPS_FILE) - ).AndReturn(deps_content) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, name, '.git') - ).AndReturn(False) - gclient.os.path.exists( - gclient.os.path.join(self.root_dir, options.entries_filename) - ).AndReturn(False) - - # This is where gclient tries to do the initial checkout. - gclient.gclient_scm.CreateSCM(self.url, self.root_dir, target).AndReturn( - gclient.gclient_scm.CreateSCM) - gclient.gclient_scm.CreateSCM.RunCommand('updatesingle', options, - self.args + ["DEPS"], []) - gclient.gclient_utils.FileWrite( - gclient.os.path.join(self.root_dir, options.entries_filename), - "entries = \\\n{ '%s': '%s'}\n" % (name, self.url)) - - self.mox.ReplayAll() - client = self._gclient_gclient(self.root_dir, options) - client.SetConfig(gclient_config) - client.RunOnDeps('update', self.args) - - def test_PrintRevInfo(self): - # TODO(aharper): no test yet for revinfo, lock it down once we've verified - # implementation for Pulse plugin - pass - - # No test for internal functions. - def test_GetAllDeps(self): - pass - def test_GetDefaultSolutionDeps(self): - pass - def test_LoadConfig(self): - pass - def test_ReadEntries(self): - pass - def test_SaveEntries(self): - pass - def test_VarImpl(self): - pass - - -if __name__ == '__main__': - import unittest - unittest.main() - -# vim: ts=2:sw=2:tw=80:et: