1#!/usr/bin/env python2 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Tool to save logs files for use by gen_smoke_tests.py.""" 18 19from __future__ import print_function 20 21import glob 22import os 23import shutil 24import sys 25 26import util 27 28ANDROID_REPOSITORY_ROOT = util.android_repository_root() 29LOGS_ROOT = os.path.join(ANDROID_REPOSITORY_ROOT, 'out', 'host', 'linux-x86', 30 'cts', 'android-cts', 'logs') 31CTS_LOGS_PATTERN = os.path.join(LOGS_ROOT, '*', '*', 32 'device_logcat_test_*.txt.gz') 33LIBCORE_DIR = os.path.join(ANDROID_REPOSITORY_ROOT, 'libcore') 34DESTINATION_DIR = os.path.join(LIBCORE_DIR, 'smoketest') 35 36 37def check_destination(): 38 """Ensures the destination directory to copy the files to exists.""" 39 if not os.path.isdir(LIBCORE_DIR): 40 raise Exception('Could not find directory ' + LIBCORE_DIR) 41 if not os.path.isdir(DESTINATION_DIR): 42 print('Making destination directory ' + 43 util.printable_path(DESTINATION_DIR)) 44 os.mkdir(DESTINATION_DIR, 0o755) 45 else: 46 print('Found destination directory ' + util.printable_path(DESTINATION_DIR)) 47 48 49def is_real_log_file(filename): 50 """Returns whether the filename is one we should use or not.""" 51 return 'latest' not in filename 52 53 54def find_all_log_files(): 55 """Finds all CTS log files in the expected directory. 56 57 Returns: 58 A list of filenames, sorted by mtime, most recent first. 59 Raises: 60 Exception: Not enough log files found. 61 """ 62 print('Looking for logs in %s' % util.printable_path(LOGS_ROOT)) 63 print('+++ ' + CTS_LOGS_PATTERN) 64 for f in glob.glob(CTS_LOGS_PATTERN): 65 print('*** ' + f) 66 sources = [f for f in glob.glob(CTS_LOGS_PATTERN) if is_real_log_file(f)] 67 if not sources: 68 raise Exception('Found no logs files!') 69 return sorted(sources, key=os.path.getmtime, reverse=True) 70 71 72def relative_source_name(source): 73 """Returns the name of a source file, relative to the logs root.""" 74 return os.path.relpath(source, LOGS_ROOT) 75 76 77def flatten_name(name): 78 """Returns a flattened version of a path, using _ to separate.""" 79 parts = [] 80 while name: 81 (head, tail) = os.path.split(name) 82 parts.insert(0, tail) 83 name = head 84 return '_'.join(parts) 85 86 87def destination_path(name): 88 """Returns the destination path for a given name (which must be flattened).""" 89 assert not os.path.dirname(name) 90 return os.path.join(DESTINATION_DIR, name) 91 92 93def get_indexes_from_user(prompt, options): 94 """Gets a sequence of indexes between 1 and max from the user. 95 96 Args: 97 prompt: A prompt to show to the user. 98 options: The options to show to the user. 99 100 Yields: 101 The indexes. 102 """ 103 for (index, option) in enumerate(options): 104 print('%d: %s' % (index + 1, option)) 105 while True: 106 print(prompt) 107 instr = sys.stdin.readline().strip() 108 if instr.lower() == 'q': 109 break 110 try: 111 index = int(instr) 112 except ValueError: 113 print('Not a valid index! Please try again') 114 continue 115 if index < 1 or index > len(options): 116 print('Not a valid index! Please try again') 117 continue 118 yield index - 1 119 120 121def do_copy(source): 122 """Copies the given source into the destination directory.""" 123 destination = destination_path(flatten_name(relative_source_name(source))) 124 if os.path.exists(destination): 125 print('File already exists: ' + util.printable_path(destination)) 126 else: 127 print('Copying %s to %s' % 128 (util.printable_path(source), util.printable_path(destination))) 129 shutil.copyfile(source, destination) 130 131 132def main(): 133 check_destination() 134 sources = find_all_log_files() 135 for index in get_indexes_from_user( 136 'Enter the number of the file to save, or Q to quit', 137 map(relative_source_name, sources)): 138 do_copy(sources[index]) 139 print('Bye!') 140 141 142main() 143