Initial Contribution
diff --git a/command.py b/command.py
new file mode 100644
index 0000000..516c2d9
--- /dev/null
+++ b/command.py
@@ -0,0 +1,116 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import optparse
+import sys
+
+from error import NoSuchProjectError
+
+class Command(object):
+ """Base class for any command line action in repo.
+ """
+
+ common = False
+ manifest = None
+ _optparse = None
+
+ @property
+ def OptionParser(self):
+ if self._optparse is None:
+ try:
+ me = 'repo %s' % self.NAME
+ usage = self.helpUsage.strip().replace('%prog', me)
+ except AttributeError:
+ usage = 'repo %s' % self.NAME
+ self._optparse = optparse.OptionParser(usage = usage)
+ self._Options(self._optparse)
+ return self._optparse
+
+ def _Options(self, p):
+ """Initialize the option parser.
+ """
+
+ def Usage(self):
+ """Display usage and terminate.
+ """
+ self.OptionParser.print_usage()
+ sys.exit(1)
+
+ def Execute(self, opt, args):
+ """Perform the action, after option parsing is complete.
+ """
+ raise NotImplementedError
+
+ def GetProjects(self, args, missing_ok=False):
+ """A list of projects that match the arguments.
+ """
+ all = self.manifest.projects
+ result = []
+
+ if not args:
+ for project in all.values():
+ if missing_ok or project.Exists:
+ result.append(project)
+ else:
+ by_path = None
+
+ for arg in args:
+ project = all.get(arg)
+
+ if not project:
+ path = os.path.abspath(arg)
+
+ if not by_path:
+ by_path = dict()
+ for p in all.values():
+ by_path[p.worktree] = p
+
+ if os.path.exists(path):
+ while path \
+ and path != '/' \
+ and path != self.manifest.topdir:
+ try:
+ project = by_path[path]
+ break
+ except KeyError:
+ path = os.path.dirname(path)
+ else:
+ try:
+ project = by_path[path]
+ except KeyError:
+ pass
+
+ if not project:
+ raise NoSuchProjectError(arg)
+ if not missing_ok and not project.Exists:
+ raise NoSuchProjectError(arg)
+
+ result.append(project)
+
+ def _getpath(x):
+ return x.relpath
+ result.sort(key=_getpath)
+ return result
+
+class InteractiveCommand(Command):
+ """Command which requires user interaction on the tty and
+ must not run within a pager, even if the user asks to.
+ """
+
+class PagedCommand(Command):
+ """Command which defaults to output in a pager, as its
+ display tends to be larger than one screen full.
+ """