class FindDependenciesTest(unittest.TestCase): @unittest.skipUnless( cloud_storage.SupportsProdaccess( os.path.realpath(cloud_storage.FindGsutil())), 'Could not find a depot_tools installation with gsutil.') def testGsutil(self): parser = optparse.OptionParser() find_dependencies.FindDependenciesCommand.AddCommandLineArgs( parser, None) options, _ = parser.parse_args([]) try: temp_dir = tempfile.mkdtemp() zip_path = os.path.join(temp_dir, 'gsutil.zip') options.zip = zip_path find_dependencies.ZipDependencies([], set(), options) if platform.system() == 'Windows': with zipfile.ZipFile(zip_path, 'r') as zip_file: zip_file.extractall(temp_dir) else: # Use unzip instead of Python zipfile to preserve file permissions. with open(os.devnull, 'w') as dev_null: subprocess.call(['unzip', zip_path], cwd=temp_dir, stdout=dev_null) third_party_path = os.path.join(temp_dir, 'telemetry', 'src', 'tools', 'telemetry', 'third_party') # __init__.py is in Chromium src, but we didn't include any repo files. open(os.path.join(third_party_path, '__init__.py'), 'a').close() gsutil_path = os.path.join(third_party_path, 'gsutil', 'gsutil') self.assertTrue(os.access(gsutil_path, os.X_OK)) with open(os.devnull, 'w') as dev_null: # gsutil with no args should print usage and exit with exit code 0. gsutil_command = [sys.executable, gsutil_path] self.assertEqual( subprocess.call(gsutil_command, stdout=dev_null), 0) # gsutil config should wait for the user and not exit with exit code 1. #gsutil_command = [sys.executable, gsutil_path, 'config', # '-o', os.path.join(temp_dir, 'config_file')] #gsutil_process = subprocess.Popen(gsutil_command, stdout=dev_null) #try: # util.WaitFor(gsutil_process.poll, timeout=0.5) # self.assertEqual(gsutil_process.returncode, 0, # msg='gsutil config failed.') #except exceptions.TimeoutException: # gsutil_process.terminate() # gsutil_process.wait() finally: shutil.rmtree(temp_dir)
def ZipDependencies(target_paths, dependencies, options): base_dir = os.path.dirname(os.path.realpath(path.GetChromiumSrcDir())) with zipfile.ZipFile(options.zip, 'w', zipfile.ZIP_DEFLATED) as zip_file: # Add dependencies to archive. for dependency_path in dependencies: path_in_archive = os.path.join( 'telemetry', os.path.relpath(dependency_path, base_dir)) zip_file.write(dependency_path, path_in_archive) # Add symlinks to executable paths, for ease of use. for target_path in target_paths: link_info = zipfile.ZipInfo( os.path.join('telemetry', os.path.basename(target_path))) link_info.create_system = 3 # Unix attributes. # 010 is regular file, 0111 is the permission bits rwxrwxrwx. link_info.external_attr = 0100777 << 16 # Octal. relative_path = os.path.relpath(target_path, base_dir) link_script = ( '#!/usr/bin/env python\n\n' 'import os\n' 'import sys\n\n\n' 'script = os.path.join(os.path.dirname(__file__), \'%s\')\n' 'os.execv(sys.executable, [sys.executable, script] + sys.argv[1:])' % relative_path) zip_file.writestr(link_info, link_script) # Add gsutil to the archive, if it's available. The gsutil in # depot_tools is modified to allow authentication using prodaccess. # TODO: If there's a gsutil in telemetry/third_party/, bootstrap_deps # will include it. Then there will be two copies of gsutil at the same # location in the archive. This can be confusing for users. gsutil_path = os.path.realpath(cloud_storage.FindGsutil()) if cloud_storage.SupportsProdaccess(gsutil_path): gsutil_base_dir = os.path.join(os.path.dirname(gsutil_path), os.pardir) gsutil_dependencies = path_set.PathSet() gsutil_dependencies.add(os.path.dirname(gsutil_path)) # Also add modules from depot_tools that are needed by gsutil. gsutil_dependencies.add(os.path.join(gsutil_base_dir, 'boto')) gsutil_dependencies.add( os.path.join(gsutil_base_dir, 'fancy_urllib')) gsutil_dependencies.add( os.path.join(gsutil_base_dir, 'retry_decorator')) gsutil_dependencies -= FindExcludedFiles(set(gsutil_dependencies), options) # Also add upload.py to the archive from depot_tools, if it is available. # This allows us to post patches without requiring a full depot_tools # install. There's no real point in including upload.py if we do not # also have gsutil, which is why this is inside the gsutil block. gsutil_dependencies.add(os.path.join(gsutil_base_dir, 'upload.py')) for dependency_path in gsutil_dependencies: path_in_archive = os.path.join( 'telemetry', os.path.relpath(path.GetTelemetryDir(), base_dir), 'third_party', os.path.relpath(dependency_path, gsutil_base_dir)) zip_file.write(dependency_path, path_in_archive)