summaryrefslogtreecommitdiffstats
path: root/command.py
diff options
context:
space:
mode:
Diffstat (limited to 'command.py')
-rw-r--r--command.py76
1 files changed, 50 insertions, 26 deletions
diff --git a/command.py b/command.py
index 5a5f468f..d543e3a8 100644
--- a/command.py
+++ b/command.py
@@ -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
147class MirrorSafeCommand(object): 171class MirrorSafeCommand(object):
148 """Command permits itself to run within a mirror, 172 """Command permits itself to run within a mirror,