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) |