• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2019 - 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"""Project config class."""
18
19import os
20
21from aidegen import constant
22from aidegen.lib import common_util
23from aidegen.lib import errors
24
25SKIP_BUILD_INFO = ('If you are sure the related modules and dependencies have '
26                   'been already built, please try to use command {} to skip '
27                   'the building process.')
28_SKIP_BUILD_CMD = 'aidegen {} -s'
29_SKIP_BUILD_WARN = (
30    'You choose "--skip-build". Skip building jar and module might increase '
31    'the risk of the absence of some jar or R/AIDL/logtags java files and '
32    'cause the red lines to appear in IDE tool.')
33_INSTANCE_NOT_EXIST_ERROR = ('The instance of {} does not exist. Please '
34                             'initialize it before using.')
35
36
37class ProjectConfig():
38    """A singleton class manages AIDEGen's configurations.
39
40    ProjectConfig is a singleton class that can be accessed in other modules.
41
42    Usage:
43        1. Main module should do it once by instantiating a ProjectConfig with
44           users' input arguments and calling init_environment().
45           args = aidegen_main.main(sys.argv[1:])
46           project_config.ProjectConfig(args).init_environment()
47        2. All others can get the ProjectConfig instance by calling
48           get_instance().
49           project_config.ProjectConfig.get_instance()
50
51    Class attributes:
52        _instance: A singleton instance of ProjectConfig.
53
54    Attributes:
55        ide_name: The IDE name which user prefer to launch.
56        is_launch_ide: A boolean for launching IDE in the end of AIDEGen.
57        depth: The depth of module referenced by source.
58        full_repo: A boolean decides import whole Android source repo.
59        is_skip_build: A boolean decides skipping building jars or modules.
60        targets: A string list with Android module names or paths.
61        verbose: A boolean. If true, display DEBUG level logs.
62        ide_installed_path: A string of IDE installed path.
63        config_reset: A boolean if true to reset all saved configurations.
64        atest_module_info: A ModuleInfo instance.
65    """
66
67    _instance = None
68
69    def __init__(self, args):
70        """ProjectConfig initialize.
71
72        Args:
73            An argparse.Namespace object holds parsed args.
74        """
75        self.ide_name = constant.IDE_NAME_DICT[args.ide[0]]
76        self.is_launch_ide = not args.no_launch
77        self.depth = args.depth
78        self.full_repo = args.android_tree
79        self.is_skip_build = args.skip_build
80        self.targets = args.targets.copy()
81        self.verbose = args.verbose
82        self.ide_installed_path = args.ide_installed_path
83        self.config_reset = args.config_reset
84        self.exclude_paths = args.exclude_paths
85        self.atest_module_info = None
86        ProjectConfig._instance = self
87
88    def init_environment(self):
89        """Initialize the environment settings for the whole project."""
90        self._show_skip_build_msg()
91        self.atest_module_info = common_util.get_atest_module_info(self.targets)
92        self.exclude_paths = _transform_exclusive_paths(
93            self.atest_module_info, self.exclude_paths)
94        self.targets = _check_whole_android_tree(self.targets, self.full_repo)
95        self.full_repo = (self.targets[0] == constant.WHOLE_ANDROID_TREE_TARGET)
96
97    def _show_skip_build_msg(self):
98        """Display different messages if users skip building targets or not."""
99        if self.is_skip_build:
100            print('\n{} {}\n'.format(
101                common_util.COLORED_INFO('Warning:'), _SKIP_BUILD_WARN))
102        else:
103            msg = SKIP_BUILD_INFO.format(
104                common_util.COLORED_INFO(
105                    _SKIP_BUILD_CMD.format(' '.join(self.targets))))
106            print('\n{} {}\n'.format(common_util.COLORED_INFO('INFO:'), msg))
107
108    @classmethod
109    def get_instance(cls):
110        """Get a singleton's instance.
111
112        Returns:
113           A singleton instance of ProjectConfig.
114
115        Raises:
116           An exception of errors.InstanceNotExistError if users didn't
117           instantiate a ProjectConfig object before calling this method.
118        """
119        if not cls._instance:
120            raise errors.InstanceNotExistError(
121                _INSTANCE_NOT_EXIST_ERROR.format(str(cls)))
122        return cls._instance
123
124
125def _check_whole_android_tree(targets, android_tree):
126    """Check if it's a building project file for the whole Android tree.
127
128    The rules:
129    1. If users command aidegen under Android root, e.g.,
130       root$ aidegen
131       that implies users would like to launch the whole Android tree, AIDEGen
132       should set the flag android_tree True.
133    2. If android_tree is True, add whole Android tree to the project.
134
135    Args:
136        targets: A list of targets to be imported.
137        android_tree: A boolean, True if it's a whole Android tree case,
138                      otherwise False.
139
140    Returns:
141        A list of targets to be built.
142    """
143    if common_util.is_android_root(os.getcwd()) and targets == ['']:
144        return [constant.WHOLE_ANDROID_TREE_TARGET]
145    new_targets = targets.copy()
146    if android_tree:
147        new_targets.insert(0, constant.WHOLE_ANDROID_TREE_TARGET)
148    return new_targets
149
150
151def is_whole_android_tree(targets, android_tree):
152    """Checks is AIDEGen going to process whole android tree.
153
154    Args:
155        targets: A list of targets to be imported.
156        android_tree: A boolean, True if it's a whole Android tree case,
157                      otherwise False.
158    Returns:
159        A boolean, True when user is going to import whole Android tree.
160    """
161    return (android_tree or
162            (common_util.is_android_root(os.getcwd()) and targets == ['']))
163
164
165def _transform_exclusive_paths(atest_module_info, exclude_paths):
166    """Transforms exclusive paths to relative paths.
167
168    Args:
169        exclude_paths: A list of strings of exclusive paths.
170
171    Returns:
172        A list of relative paths.
173    """
174    if not exclude_paths:
175        return None
176    excludes = []
177    for path in exclude_paths:
178        exclude_path, _ = common_util.get_related_paths(atest_module_info, path)
179        excludes.append(exclude_path)
180    return excludes
181