diff options
Diffstat (limited to 'command.py')
| -rw-r--r-- | command.py | 76 |
1 files changed, 50 insertions, 26 deletions
| @@ -60,6 +60,32 @@ class Command(object): | |||
| 60 | """ | 60 | """ |
| 61 | raise NotImplementedError | 61 | raise NotImplementedError |
| 62 | 62 | ||
| 63 | def _ResetPathToProjectMap(self, projects): | ||
| 64 | self._by_path = dict((p.worktree, p) for p in projects) | ||
| 65 | |||
| 66 | def _UpdatePathToProjectMap(self, project): | ||
| 67 | self._by_path[project.worktree] = project | ||
| 68 | |||
| 69 | def _GetProjectByPath(self, path): | ||
| 70 | project = None | ||
| 71 | if os.path.exists(path): | ||
| 72 | oldpath = None | ||
| 73 | while path \ | ||
| 74 | and path != oldpath \ | ||
| 75 | and path != self.manifest.topdir: | ||
| 76 | try: | ||
| 77 | project = self._by_path[path] | ||
| 78 | break | ||
| 79 | except KeyError: | ||
| 80 | oldpath = path | ||
| 81 | path = os.path.dirname(path) | ||
| 82 | else: | ||
| 83 | try: | ||
| 84 | project = self._by_path[path] | ||
| 85 | except KeyError: | ||
| 86 | pass | ||
| 87 | return project | ||
| 88 | |||
| 63 | def GetProjects(self, args, missing_ok=False): | 89 | def GetProjects(self, args, missing_ok=False): |
| 64 | """A list of projects that match the arguments. | 90 | """A list of projects that match the arguments. |
| 65 | """ | 91 | """ |
| @@ -74,40 +100,38 @@ class Command(object): | |||
| 74 | groups = [x for x in re.split('[,\s]+', groups) if x] | 100 | groups = [x for x in re.split('[,\s]+', groups) if x] |
| 75 | 101 | ||
| 76 | if not args: | 102 | if not args: |
| 77 | for project in all_projects.values(): | 103 | all_projects_list = all_projects.values() |
| 104 | derived_projects = [] | ||
| 105 | for project in all_projects_list: | ||
| 106 | if project.Registered: | ||
| 107 | # Do not search registered subproject for derived projects | ||
| 108 | # since its parent has been searched already | ||
| 109 | continue | ||
| 110 | derived_projects.extend(project.GetDerivedSubprojects()) | ||
| 111 | all_projects_list.extend(derived_projects) | ||
| 112 | for project in all_projects_list: | ||
| 78 | if ((missing_ok or project.Exists) and | 113 | if ((missing_ok or project.Exists) and |
| 79 | project.MatchesGroups(groups)): | 114 | project.MatchesGroups(groups)): |
| 80 | result.append(project) | 115 | result.append(project) |
| 81 | else: | 116 | else: |
| 82 | by_path = None | 117 | self._ResetPathToProjectMap(all_projects.values()) |
| 83 | 118 | ||
| 84 | for arg in args: | 119 | for arg in args: |
| 85 | project = all_projects.get(arg) | 120 | project = all_projects.get(arg) |
| 86 | 121 | ||
| 87 | if not project: | 122 | if not project: |
| 88 | path = os.path.abspath(arg).replace('\\', '/') | 123 | path = os.path.abspath(arg).replace('\\', '/') |
| 89 | 124 | project = self._GetProjectByPath(path) | |
| 90 | if not by_path: | 125 | |
| 91 | by_path = dict() | 126 | # If it's not a derived project, update path->project mapping and |
| 92 | for p in all_projects.values(): | 127 | # search again, as arg might actually point to a derived subproject. |
| 93 | by_path[p.worktree] = p | 128 | if project and not project.Derived: |
| 94 | 129 | search_again = False | |
| 95 | if os.path.exists(path): | 130 | for subproject in project.GetDerivedSubprojects(): |
| 96 | oldpath = None | 131 | self._UpdatePathToProjectMap(subproject) |
| 97 | while path \ | 132 | search_again = True |
| 98 | and path != oldpath \ | 133 | if search_again: |
| 99 | and path != self.manifest.topdir: | 134 | project = self._GetProjectByPath(path) or project |
| 100 | try: | ||
| 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 | 135 | ||
| 112 | if not project: | 136 | if not project: |
| 113 | raise NoSuchProjectError(arg) | 137 | raise NoSuchProjectError(arg) |
| @@ -123,7 +147,7 @@ class Command(object): | |||
| 123 | result.sort(key=_getpath) | 147 | result.sort(key=_getpath) |
| 124 | return result | 148 | return result |
| 125 | 149 | ||
| 126 | # pylint: disable-msg=W0223 | 150 | # pylint: disable=W0223 |
| 127 | # Pylint warns that the `InteractiveCommand` and `PagedCommand` classes do not | 151 | # Pylint warns that the `InteractiveCommand` and `PagedCommand` classes do not |
| 128 | # override method `Execute` which is abstract in `Command`. Since that method | 152 | # override method `Execute` which is abstract in `Command`. Since that method |
| 129 | # is always implemented in classes derived from `InteractiveCommand` and | 153 | # is always implemented in classes derived from `InteractiveCommand` and |
| @@ -142,7 +166,7 @@ class PagedCommand(Command): | |||
| 142 | def WantPager(self, opt): | 166 | def WantPager(self, opt): |
| 143 | return True | 167 | return True |
| 144 | 168 | ||
| 145 | # pylint: enable-msg=W0223 | 169 | # pylint: enable=W0223 |
| 146 | 170 | ||
| 147 | class MirrorSafeCommand(object): | 171 | class MirrorSafeCommand(object): |
| 148 | """Command permits itself to run within a mirror, | 172 | """Command permits itself to run within a mirror, |
