diff options
Diffstat (limited to 'command.py')
| -rw-r--r-- | command.py | 115 |
1 files changed, 89 insertions, 26 deletions
| @@ -22,6 +22,7 @@ import sys | |||
| 22 | from error import NoSuchProjectError | 22 | from error import NoSuchProjectError |
| 23 | from error import InvalidProjectGroupsError | 23 | from error import InvalidProjectGroupsError |
| 24 | 24 | ||
| 25 | |||
| 25 | class Command(object): | 26 | class Command(object): |
| 26 | """Base class for any command line action in repo. | 27 | """Base class for any command line action in repo. |
| 27 | """ | 28 | """ |
| @@ -33,6 +34,27 @@ class Command(object): | |||
| 33 | def WantPager(self, opt): | 34 | def WantPager(self, opt): |
| 34 | return False | 35 | return False |
| 35 | 36 | ||
| 37 | def ReadEnvironmentOptions(self, opts): | ||
| 38 | """ Set options from environment variables. """ | ||
| 39 | |||
| 40 | env_options = self._RegisteredEnvironmentOptions() | ||
| 41 | |||
| 42 | for env_key, opt_key in env_options.items(): | ||
| 43 | # Get the user-set option value if any | ||
| 44 | opt_value = getattr(opts, opt_key) | ||
| 45 | |||
| 46 | # If the value is set, it means the user has passed it as a command | ||
| 47 | # line option, and we should use that. Otherwise we can try to set it | ||
| 48 | # with the value from the corresponding environment variable. | ||
| 49 | if opt_value is not None: | ||
| 50 | continue | ||
| 51 | |||
| 52 | env_value = os.environ.get(env_key) | ||
| 53 | if env_value is not None: | ||
| 54 | setattr(opts, opt_key, env_value) | ||
| 55 | |||
| 56 | return opts | ||
| 57 | |||
| 36 | @property | 58 | @property |
| 37 | def OptionParser(self): | 59 | def OptionParser(self): |
| 38 | if self._optparse is None: | 60 | if self._optparse is None: |
| @@ -49,6 +71,24 @@ class Command(object): | |||
| 49 | """Initialize the option parser. | 71 | """Initialize the option parser. |
| 50 | """ | 72 | """ |
| 51 | 73 | ||
| 74 | def _RegisteredEnvironmentOptions(self): | ||
| 75 | """Get options that can be set from environment variables. | ||
| 76 | |||
| 77 | Return a dictionary mapping environment variable name | ||
| 78 | to option key name that it can override. | ||
| 79 | |||
| 80 | Example: {'REPO_MY_OPTION': 'my_option'} | ||
| 81 | |||
| 82 | Will allow the option with key value 'my_option' to be set | ||
| 83 | from the value in the environment variable named 'REPO_MY_OPTION'. | ||
| 84 | |||
| 85 | Note: This does not work properly for options that are explicitly | ||
| 86 | set to None by the user, or options that are defined with a | ||
| 87 | default value other than None. | ||
| 88 | |||
| 89 | """ | ||
| 90 | return {} | ||
| 91 | |||
| 52 | def Usage(self): | 92 | def Usage(self): |
| 53 | """Display usage and terminate. | 93 | """Display usage and terminate. |
| 54 | """ | 94 | """ |
| @@ -60,7 +100,33 @@ class Command(object): | |||
| 60 | """ | 100 | """ |
| 61 | raise NotImplementedError | 101 | raise NotImplementedError |
| 62 | 102 | ||
| 63 | def GetProjects(self, args, missing_ok=False): | 103 | def _ResetPathToProjectMap(self, projects): |
| 104 | self._by_path = dict((p.worktree, p) for p in projects) | ||
| 105 | |||
| 106 | def _UpdatePathToProjectMap(self, project): | ||
| 107 | self._by_path[project.worktree] = project | ||
| 108 | |||
| 109 | def _GetProjectByPath(self, path): | ||
| 110 | project = None | ||
| 111 | if os.path.exists(path): | ||
| 112 | oldpath = None | ||
| 113 | while path \ | ||
| 114 | and path != oldpath \ | ||
| 115 | and path != self.manifest.topdir: | ||
| 116 | try: | ||
| 117 | project = self._by_path[path] | ||
| 118 | break | ||
| 119 | except KeyError: | ||
| 120 | oldpath = path | ||
| 121 | path = os.path.dirname(path) | ||
| 122 | else: | ||
| 123 | try: | ||
| 124 | project = self._by_path[path] | ||
| 125 | except KeyError: | ||
| 126 | pass | ||
| 127 | return project | ||
| 128 | |||
| 129 | def GetProjects(self, args, missing_ok=False, submodules_ok=False): | ||
| 64 | """A list of projects that match the arguments. | 130 | """A list of projects that match the arguments. |
| 65 | """ | 131 | """ |
| 66 | all_projects = self.manifest.projects | 132 | all_projects = self.manifest.projects |
| @@ -71,43 +137,40 @@ class Command(object): | |||
| 71 | groups = mp.config.GetString('manifest.groups') | 137 | groups = mp.config.GetString('manifest.groups') |
| 72 | if not groups: | 138 | if not groups: |
| 73 | groups = 'all,-notdefault,platform-' + platform.system().lower() | 139 | groups = 'all,-notdefault,platform-' + platform.system().lower() |
| 74 | groups = [x for x in re.split('[,\s]+', groups) if x] | 140 | groups = [x for x in re.split(r'[,\s]+', groups) if x] |
| 75 | 141 | ||
| 76 | if not args: | 142 | if not args: |
| 77 | for project in all_projects.values(): | 143 | all_projects_list = all_projects.values() |
| 144 | derived_projects = {} | ||
| 145 | for project in all_projects_list: | ||
| 146 | if submodules_ok or project.sync_s: | ||
| 147 | derived_projects.update((p.name, p) | ||
| 148 | for p in project.GetDerivedSubprojects()) | ||
| 149 | all_projects_list.extend(derived_projects.values()) | ||
| 150 | for project in all_projects_list: | ||
| 78 | if ((missing_ok or project.Exists) and | 151 | if ((missing_ok or project.Exists) and |
| 79 | project.MatchesGroups(groups)): | 152 | project.MatchesGroups(groups)): |
| 80 | result.append(project) | 153 | result.append(project) |
| 81 | else: | 154 | else: |
| 82 | by_path = None | 155 | self._ResetPathToProjectMap(all_projects.values()) |
| 83 | 156 | ||
| 84 | for arg in args: | 157 | for arg in args: |
| 85 | project = all_projects.get(arg) | 158 | project = all_projects.get(arg) |
| 86 | 159 | ||
| 87 | if not project: | 160 | if not project: |
| 88 | path = os.path.abspath(arg).replace('\\', '/') | 161 | path = os.path.abspath(arg).replace('\\', '/') |
| 89 | 162 | project = self._GetProjectByPath(path) | |
| 90 | if not by_path: | 163 | |
| 91 | by_path = dict() | 164 | # If it's not a derived project, update path->project mapping and |
| 92 | for p in all_projects.values(): | 165 | # search again, as arg might actually point to a derived subproject. |
| 93 | by_path[p.worktree] = p | 166 | if (project and not project.Derived and |
| 94 | 167 | (submodules_ok or project.sync_s)): | |
| 95 | if os.path.exists(path): | 168 | search_again = False |
| 96 | oldpath = None | 169 | for subproject in project.GetDerivedSubprojects(): |
| 97 | while path \ | 170 | self._UpdatePathToProjectMap(subproject) |
| 98 | and path != oldpath \ | 171 | search_again = True |
| 99 | and path != self.manifest.topdir: | 172 | if search_again: |
| 100 | try: | 173 | project = self._GetProjectByPath(path) or project |
| 101 | project = by_path[path] | ||
| 102 | break | ||
| 103 | except KeyError: | ||
| 104 | oldpath = path | ||
| 105 | path = os.path.dirname(path) | ||
| 106 | else: | ||
| 107 | try: | ||
| 108 | project = by_path[path] | ||
| 109 | except KeyError: | ||
| 110 | pass | ||
| 111 | 174 | ||
| 112 | if not project: | 175 | if not project: |
| 113 | raise NoSuchProjectError(arg) | 176 | raise NoSuchProjectError(arg) |
