1#!/usr/bin/python3 -B
2
3# Copyright 2021 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"""ojluni_modify_expectation is a command-line tool for modifying the EXPECTED_UPSTREAM file."""
17
18import argparse
19import sys
20from typing import Sequence
21
22from common_util import ExpectedUpstreamFile
23from common_util import LIBCORE_DIR
24from common_util import OpenjdkFinder
25
26# Import git only after common_util because common_util will
27# produce informative error
28from git import Commit
29from git import Repo
30from gitdb.exc import BadName
31
32LIBCORE_REPO = Repo(LIBCORE_DIR.as_posix())
33
34
35def error_and_exit(msg: str) -> None:
36  print(f'Error: {msg}', file=sys.stderr)
37  sys.exit(1)
38
39
40def get_commit_or_exit(git_ref: str) -> Commit:
41  try:
42    return LIBCORE_REPO.commit(git_ref)
43  except BadName as e:
44    error_and_exit(f'{e}')
45
46
47def main(argv: Sequence[str]) -> None:
48  arg_parser = argparse.ArgumentParser(
49      description='Set an entry in EXCPETED_UPSTREAM to the given version if'
50                  ' the current and given version are identical.')
51  arg_parser.add_argument(
52      'target_ref', nargs=1,
53      help='A git tag or commit in the upstream-openjdkXXX branch')
54  arg_parser.add_argument(
55      'source_ref', nargs='?',
56      help='A git tag or commit in the upstream-openjdkXXX branch')
57
58  args = arg_parser.parse_args(argv)
59
60  target_ref = args.target_ref[0]
61  source_ref = args.source_ref
62  commit = get_commit_or_exit(target_ref)
63
64  expected_upstream_file = ExpectedUpstreamFile()
65  expected_entries = expected_upstream_file.read_all_entries()
66
67  new_finder = OpenjdkFinder(commit)
68
69  for expected_entry in expected_entries:
70    if expected_entry.git_ref == target_ref:
71      continue
72
73    # If the source_ref is specified, skip any existing different source refs.
74    if source_ref is not None and expected_entry.git_ref != source_ref:
75      continue
76
77    current_commit = LIBCORE_REPO.commit(expected_entry.git_ref)
78    current_finder = OpenjdkFinder(current_commit)
79    if not current_finder.has_file(expected_entry.src_path):
80      error_and_exit(f'{expected_entry.src_path} is not found in '
81                     f'{expected_entry.git_ref}')
82
83    current_blob = current_commit.tree[expected_entry.src_path]
84
85    # Try to guess the new source path in the new version
86    new_src_path = expected_entry.src_path
87    if new_finder.has_file(new_src_path):
88      pass
89    else:
90      new_src_path = new_finder.find_src_path_from_ojluni_path(
91          expected_entry.dst_path)
92      if new_src_path is None:
93        print(f"Warning: can't find the upstream path for "
94              f"{expected_entry.dst_path}", file=sys.stderr)
95        continue
96
97    new_blob = commit.tree[new_src_path]
98    if current_blob.data_stream.read() == new_blob.data_stream.read():
99      expected_entry.git_ref = target_ref
100      expected_entry.src_path = new_src_path
101
102  expected_upstream_file.write_all_entries(expected_entries)
103
104
105if __name__ == '__main__':
106  main(sys.argv[1:])
107