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