diff options
43 files changed, 148 insertions, 12 deletions
| @@ -84,6 +84,7 @@ def _Color(fg=None, bg=None, attr=None): | |||
| 84 | code = '' | 84 | code = '' |
| 85 | return code | 85 | return code |
| 86 | 86 | ||
| 87 | |||
| 87 | DEFAULT = None | 88 | DEFAULT = None |
| 88 | 89 | ||
| 89 | 90 | ||
| @@ -236,6 +236,7 @@ class InteractiveCommand(Command): | |||
| 236 | """Command which requires user interaction on the tty and | 236 | """Command which requires user interaction on the tty and |
| 237 | must not run within a pager, even if the user asks to. | 237 | must not run within a pager, even if the user asks to. |
| 238 | """ | 238 | """ |
| 239 | |||
| 239 | def WantPager(self, _opt): | 240 | def WantPager(self, _opt): |
| 240 | return False | 241 | return False |
| 241 | 242 | ||
| @@ -244,6 +245,7 @@ class PagedCommand(Command): | |||
| 244 | """Command which defaults to output in a pager, as its | 245 | """Command which defaults to output in a pager, as its |
| 245 | display tends to be larger than one screen full. | 246 | display tends to be larger than one screen full. |
| 246 | """ | 247 | """ |
| 248 | |||
| 247 | def WantPager(self, _opt): | 249 | def WantPager(self, _opt): |
| 248 | return True | 250 | return True |
| 249 | 251 | ||
| @@ -24,6 +24,7 @@ import tempfile | |||
| 24 | from error import EditorError | 24 | from error import EditorError |
| 25 | import platform_utils | 25 | import platform_utils |
| 26 | 26 | ||
| 27 | |||
| 27 | class Editor(object): | 28 | class Editor(object): |
| 28 | """Manages the user's preferred text editor.""" | 29 | """Manages the user's preferred text editor.""" |
| 29 | 30 | ||
| @@ -14,21 +14,26 @@ | |||
| 14 | # See the License for the specific language governing permissions and | 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. | 15 | # limitations under the License. |
| 16 | 16 | ||
| 17 | |||
| 17 | class ManifestParseError(Exception): | 18 | class ManifestParseError(Exception): |
| 18 | """Failed to parse the manifest file. | 19 | """Failed to parse the manifest file. |
| 19 | """ | 20 | """ |
| 20 | 21 | ||
| 22 | |||
| 21 | class ManifestInvalidRevisionError(Exception): | 23 | class ManifestInvalidRevisionError(Exception): |
| 22 | """The revision value in a project is incorrect. | 24 | """The revision value in a project is incorrect. |
| 23 | """ | 25 | """ |
| 24 | 26 | ||
| 27 | |||
| 25 | class ManifestInvalidPathError(Exception): | 28 | class ManifestInvalidPathError(Exception): |
| 26 | """A path used in <copyfile> or <linkfile> is incorrect. | 29 | """A path used in <copyfile> or <linkfile> is incorrect. |
| 27 | """ | 30 | """ |
| 28 | 31 | ||
| 32 | |||
| 29 | class NoManifestException(Exception): | 33 | class NoManifestException(Exception): |
| 30 | """The required manifest does not exist. | 34 | """The required manifest does not exist. |
| 31 | """ | 35 | """ |
| 36 | |||
| 32 | def __init__(self, path, reason): | 37 | def __init__(self, path, reason): |
| 33 | super(NoManifestException, self).__init__() | 38 | super(NoManifestException, self).__init__() |
| 34 | self.path = path | 39 | self.path = path |
| @@ -37,9 +42,11 @@ class NoManifestException(Exception): | |||
| 37 | def __str__(self): | 42 | def __str__(self): |
| 38 | return self.reason | 43 | return self.reason |
| 39 | 44 | ||
| 45 | |||
| 40 | class EditorError(Exception): | 46 | class EditorError(Exception): |
| 41 | """Unspecified error from the user's text editor. | 47 | """Unspecified error from the user's text editor. |
| 42 | """ | 48 | """ |
| 49 | |||
| 43 | def __init__(self, reason): | 50 | def __init__(self, reason): |
| 44 | super(EditorError, self).__init__() | 51 | super(EditorError, self).__init__() |
| 45 | self.reason = reason | 52 | self.reason = reason |
| @@ -47,9 +54,11 @@ class EditorError(Exception): | |||
| 47 | def __str__(self): | 54 | def __str__(self): |
| 48 | return self.reason | 55 | return self.reason |
| 49 | 56 | ||
| 57 | |||
| 50 | class GitError(Exception): | 58 | class GitError(Exception): |
| 51 | """Unspecified internal error from git. | 59 | """Unspecified internal error from git. |
| 52 | """ | 60 | """ |
| 61 | |||
| 53 | def __init__(self, command): | 62 | def __init__(self, command): |
| 54 | super(GitError, self).__init__() | 63 | super(GitError, self).__init__() |
| 55 | self.command = command | 64 | self.command = command |
| @@ -57,9 +66,11 @@ class GitError(Exception): | |||
| 57 | def __str__(self): | 66 | def __str__(self): |
| 58 | return self.command | 67 | return self.command |
| 59 | 68 | ||
| 69 | |||
| 60 | class UploadError(Exception): | 70 | class UploadError(Exception): |
| 61 | """A bundle upload to Gerrit did not succeed. | 71 | """A bundle upload to Gerrit did not succeed. |
| 62 | """ | 72 | """ |
| 73 | |||
| 63 | def __init__(self, reason): | 74 | def __init__(self, reason): |
| 64 | super(UploadError, self).__init__() | 75 | super(UploadError, self).__init__() |
| 65 | self.reason = reason | 76 | self.reason = reason |
| @@ -67,9 +78,11 @@ class UploadError(Exception): | |||
| 67 | def __str__(self): | 78 | def __str__(self): |
| 68 | return self.reason | 79 | return self.reason |
| 69 | 80 | ||
| 81 | |||
| 70 | class DownloadError(Exception): | 82 | class DownloadError(Exception): |
| 71 | """Cannot download a repository. | 83 | """Cannot download a repository. |
| 72 | """ | 84 | """ |
| 85 | |||
| 73 | def __init__(self, reason): | 86 | def __init__(self, reason): |
| 74 | super(DownloadError, self).__init__() | 87 | super(DownloadError, self).__init__() |
| 75 | self.reason = reason | 88 | self.reason = reason |
| @@ -77,9 +90,11 @@ class DownloadError(Exception): | |||
| 77 | def __str__(self): | 90 | def __str__(self): |
| 78 | return self.reason | 91 | return self.reason |
| 79 | 92 | ||
| 93 | |||
| 80 | class NoSuchProjectError(Exception): | 94 | class NoSuchProjectError(Exception): |
| 81 | """A specified project does not exist in the work tree. | 95 | """A specified project does not exist in the work tree. |
| 82 | """ | 96 | """ |
| 97 | |||
| 83 | def __init__(self, name=None): | 98 | def __init__(self, name=None): |
| 84 | super(NoSuchProjectError, self).__init__() | 99 | super(NoSuchProjectError, self).__init__() |
| 85 | self.name = name | 100 | self.name = name |
| @@ -93,6 +108,7 @@ class NoSuchProjectError(Exception): | |||
| 93 | class InvalidProjectGroupsError(Exception): | 108 | class InvalidProjectGroupsError(Exception): |
| 94 | """A specified project is not suitable for the specified groups | 109 | """A specified project is not suitable for the specified groups |
| 95 | """ | 110 | """ |
| 111 | |||
| 96 | def __init__(self, name=None): | 112 | def __init__(self, name=None): |
| 97 | super(InvalidProjectGroupsError, self).__init__() | 113 | super(InvalidProjectGroupsError, self).__init__() |
| 98 | self.name = name | 114 | self.name = name |
| @@ -102,15 +118,18 @@ class InvalidProjectGroupsError(Exception): | |||
| 102 | return 'in current directory' | 118 | return 'in current directory' |
| 103 | return self.name | 119 | return self.name |
| 104 | 120 | ||
| 121 | |||
| 105 | class RepoChangedException(Exception): | 122 | class RepoChangedException(Exception): |
| 106 | """Thrown if 'repo sync' results in repo updating its internal | 123 | """Thrown if 'repo sync' results in repo updating its internal |
| 107 | repo or manifest repositories. In this special case we must | 124 | repo or manifest repositories. In this special case we must |
| 108 | use exec to re-execute repo with the new code and manifest. | 125 | use exec to re-execute repo with the new code and manifest. |
| 109 | """ | 126 | """ |
| 127 | |||
| 110 | def __init__(self, extra_args=None): | 128 | def __init__(self, extra_args=None): |
| 111 | super(RepoChangedException, self).__init__() | 129 | super(RepoChangedException, self).__init__() |
| 112 | self.extra_args = extra_args or [] | 130 | self.extra_args = extra_args or [] |
| 113 | 131 | ||
| 132 | |||
| 114 | class HookError(Exception): | 133 | class HookError(Exception): |
| 115 | """Thrown if a 'repo-hook' could not be run. | 134 | """Thrown if a 'repo-hook' could not be run. |
| 116 | 135 | ||
diff --git a/event_log.py b/event_log.py index 45800a59..5dd9db66 100644 --- a/event_log.py +++ b/event_log.py | |||
| @@ -23,6 +23,7 @@ TASK_COMMAND = 'command' | |||
| 23 | TASK_SYNC_NETWORK = 'sync-network' | 23 | TASK_SYNC_NETWORK = 'sync-network' |
| 24 | TASK_SYNC_LOCAL = 'sync-local' | 24 | TASK_SYNC_LOCAL = 'sync-local' |
| 25 | 25 | ||
| 26 | |||
| 26 | class EventLog(object): | 27 | class EventLog(object): |
| 27 | """Event log that records events that occurred during a repo invocation. | 28 | """Event log that records events that occurred during a repo invocation. |
| 28 | 29 | ||
| @@ -165,6 +166,7 @@ class EventLog(object): | |||
| 165 | # An integer id that is unique across this invocation of the program. | 166 | # An integer id that is unique across this invocation of the program. |
| 166 | _EVENT_ID = multiprocessing.Value('i', 1) | 167 | _EVENT_ID = multiprocessing.Value('i', 1) |
| 167 | 168 | ||
| 169 | |||
| 168 | def _NextEventId(): | 170 | def _NextEventId(): |
| 169 | """Helper function for grabbing the next unique id. | 171 | """Helper function for grabbing the next unique id. |
| 170 | 172 | ||
diff --git a/git_command.py b/git_command.py index df39ec09..c7e94fd0 100644 --- a/git_command.py +++ b/git_command.py | |||
| @@ -48,6 +48,7 @@ _ssh_proxy_path = None | |||
| 48 | _ssh_sock_path = None | 48 | _ssh_sock_path = None |
| 49 | _ssh_clients = [] | 49 | _ssh_clients = [] |
| 50 | 50 | ||
| 51 | |||
| 51 | def ssh_sock(create=True): | 52 | def ssh_sock(create=True): |
| 52 | global _ssh_sock_path | 53 | global _ssh_sock_path |
| 53 | if _ssh_sock_path is None: | 54 | if _ssh_sock_path is None: |
| @@ -61,6 +62,7 @@ def ssh_sock(create=True): | |||
| 61 | 'master-%r@%h:%p') | 62 | 'master-%r@%h:%p') |
| 62 | return _ssh_sock_path | 63 | return _ssh_sock_path |
| 63 | 64 | ||
| 65 | |||
| 64 | def _ssh_proxy(): | 66 | def _ssh_proxy(): |
| 65 | global _ssh_proxy_path | 67 | global _ssh_proxy_path |
| 66 | if _ssh_proxy_path is None: | 68 | if _ssh_proxy_path is None: |
| @@ -69,15 +71,18 @@ def _ssh_proxy(): | |||
| 69 | 'git_ssh') | 71 | 'git_ssh') |
| 70 | return _ssh_proxy_path | 72 | return _ssh_proxy_path |
| 71 | 73 | ||
| 74 | |||
| 72 | def _add_ssh_client(p): | 75 | def _add_ssh_client(p): |
| 73 | _ssh_clients.append(p) | 76 | _ssh_clients.append(p) |
| 74 | 77 | ||
| 78 | |||
| 75 | def _remove_ssh_client(p): | 79 | def _remove_ssh_client(p): |
| 76 | try: | 80 | try: |
| 77 | _ssh_clients.remove(p) | 81 | _ssh_clients.remove(p) |
| 78 | except ValueError: | 82 | except ValueError: |
| 79 | pass | 83 | pass |
| 80 | 84 | ||
| 85 | |||
| 81 | def terminate_ssh_clients(): | 86 | def terminate_ssh_clients(): |
| 82 | global _ssh_clients | 87 | global _ssh_clients |
| 83 | for p in _ssh_clients: | 88 | for p in _ssh_clients: |
| @@ -88,8 +93,10 @@ def terminate_ssh_clients(): | |||
| 88 | pass | 93 | pass |
| 89 | _ssh_clients = [] | 94 | _ssh_clients = [] |
| 90 | 95 | ||
| 96 | |||
| 91 | _git_version = None | 97 | _git_version = None |
| 92 | 98 | ||
| 99 | |||
| 93 | class _GitCall(object): | 100 | class _GitCall(object): |
| 94 | def version_tuple(self): | 101 | def version_tuple(self): |
| 95 | global _git_version | 102 | global _git_version |
| @@ -102,11 +109,14 @@ class _GitCall(object): | |||
| 102 | 109 | ||
| 103 | def __getattr__(self, name): | 110 | def __getattr__(self, name): |
| 104 | name = name.replace('_', '-') | 111 | name = name.replace('_', '-') |
| 112 | |||
| 105 | def fun(*cmdv): | 113 | def fun(*cmdv): |
| 106 | command = [name] | 114 | command = [name] |
| 107 | command.extend(cmdv) | 115 | command.extend(cmdv) |
| 108 | return GitCommand(None, command).Wait() == 0 | 116 | return GitCommand(None, command).Wait() == 0 |
| 109 | return fun | 117 | return fun |
| 118 | |||
| 119 | |||
| 110 | git = _GitCall() | 120 | git = _GitCall() |
| 111 | 121 | ||
| 112 | 122 | ||
| @@ -187,8 +197,10 @@ class UserAgent(object): | |||
| 187 | 197 | ||
| 188 | return self._git_ua | 198 | return self._git_ua |
| 189 | 199 | ||
| 200 | |||
| 190 | user_agent = UserAgent() | 201 | user_agent = UserAgent() |
| 191 | 202 | ||
| 203 | |||
| 192 | def git_require(min_version, fail=False, msg=''): | 204 | def git_require(min_version, fail=False, msg=''): |
| 193 | git_version = git.version_tuple() | 205 | git_version = git.version_tuple() |
| 194 | if min_version <= git_version: | 206 | if min_version <= git_version: |
| @@ -201,9 +213,11 @@ def git_require(min_version, fail=False, msg=''): | |||
| 201 | sys.exit(1) | 213 | sys.exit(1) |
| 202 | return False | 214 | return False |
| 203 | 215 | ||
| 216 | |||
| 204 | def _setenv(env, name, value): | 217 | def _setenv(env, name, value): |
| 205 | env[name] = value.encode() | 218 | env[name] = value.encode() |
| 206 | 219 | ||
| 220 | |||
| 207 | class GitCommand(object): | 221 | class GitCommand(object): |
| 208 | def __init__(self, | 222 | def __init__(self, |
| 209 | project, | 223 | project, |
diff --git a/git_config.py b/git_config.py index 13fbda24..5fb61d21 100644 --- a/git_config.py +++ b/git_config.py | |||
| @@ -59,18 +59,23 @@ ID_RE = re.compile(r'^[0-9a-f]{40}$') | |||
| 59 | 59 | ||
| 60 | REVIEW_CACHE = dict() | 60 | REVIEW_CACHE = dict() |
| 61 | 61 | ||
| 62 | |||
| 62 | def IsChange(rev): | 63 | def IsChange(rev): |
| 63 | return rev.startswith(R_CHANGES) | 64 | return rev.startswith(R_CHANGES) |
| 64 | 65 | ||
| 66 | |||
| 65 | def IsId(rev): | 67 | def IsId(rev): |
| 66 | return ID_RE.match(rev) | 68 | return ID_RE.match(rev) |
| 67 | 69 | ||
| 70 | |||
| 68 | def IsTag(rev): | 71 | def IsTag(rev): |
| 69 | return rev.startswith(R_TAGS) | 72 | return rev.startswith(R_TAGS) |
| 70 | 73 | ||
| 74 | |||
| 71 | def IsImmutable(rev): | 75 | def IsImmutable(rev): |
| 72 | return IsChange(rev) or IsId(rev) or IsTag(rev) | 76 | return IsChange(rev) or IsId(rev) or IsTag(rev) |
| 73 | 77 | ||
| 78 | |||
| 74 | def _key(name): | 79 | def _key(name): |
| 75 | parts = name.split('.') | 80 | parts = name.split('.') |
| 76 | if len(parts) < 2: | 81 | if len(parts) < 2: |
| @@ -79,6 +84,7 @@ def _key(name): | |||
| 79 | parts[-1] = parts[-1].lower() | 84 | parts[-1] = parts[-1].lower() |
| 80 | return '.'.join(parts) | 85 | return '.'.join(parts) |
| 81 | 86 | ||
| 87 | |||
| 82 | class GitConfig(object): | 88 | class GitConfig(object): |
| 83 | _ForUser = None | 89 | _ForUser = None |
| 84 | 90 | ||
| @@ -392,6 +398,7 @@ _master_keys = set() | |||
| 392 | _ssh_master = True | 398 | _ssh_master = True |
| 393 | _master_keys_lock = None | 399 | _master_keys_lock = None |
| 394 | 400 | ||
| 401 | |||
| 395 | def init_ssh(): | 402 | def init_ssh(): |
| 396 | """Should be called once at the start of repo to init ssh master handling. | 403 | """Should be called once at the start of repo to init ssh master handling. |
| 397 | 404 | ||
| @@ -401,6 +408,7 @@ def init_ssh(): | |||
| 401 | assert _master_keys_lock is None, "Should only call init_ssh once" | 408 | assert _master_keys_lock is None, "Should only call init_ssh once" |
| 402 | _master_keys_lock = _threading.Lock() | 409 | _master_keys_lock = _threading.Lock() |
| 403 | 410 | ||
| 411 | |||
| 404 | def _open_ssh(host, port=None): | 412 | def _open_ssh(host, port=None): |
| 405 | global _ssh_master | 413 | global _ssh_master |
| 406 | 414 | ||
| @@ -479,6 +487,7 @@ def _open_ssh(host, port=None): | |||
| 479 | finally: | 487 | finally: |
| 480 | _master_keys_lock.release() | 488 | _master_keys_lock.release() |
| 481 | 489 | ||
| 490 | |||
| 482 | def close_ssh(): | 491 | def close_ssh(): |
| 483 | global _master_keys_lock | 492 | global _master_keys_lock |
| 484 | 493 | ||
| @@ -503,15 +512,18 @@ def close_ssh(): | |||
| 503 | # We're done with the lock, so we can delete it. | 512 | # We're done with the lock, so we can delete it. |
| 504 | _master_keys_lock = None | 513 | _master_keys_lock = None |
| 505 | 514 | ||
| 515 | |||
| 506 | URI_SCP = re.compile(r'^([^@:]*@?[^:/]{1,}):') | 516 | URI_SCP = re.compile(r'^([^@:]*@?[^:/]{1,}):') |
| 507 | URI_ALL = re.compile(r'^([a-z][a-z+-]*)://([^@/]*@?[^/]*)/') | 517 | URI_ALL = re.compile(r'^([a-z][a-z+-]*)://([^@/]*@?[^/]*)/') |
| 508 | 518 | ||
| 519 | |||
| 509 | def GetSchemeFromUrl(url): | 520 | def GetSchemeFromUrl(url): |
| 510 | m = URI_ALL.match(url) | 521 | m = URI_ALL.match(url) |
| 511 | if m: | 522 | if m: |
| 512 | return m.group(1) | 523 | return m.group(1) |
| 513 | return None | 524 | return None |
| 514 | 525 | ||
| 526 | |||
| 515 | @contextlib.contextmanager | 527 | @contextlib.contextmanager |
| 516 | def GetUrlCookieFile(url, quiet): | 528 | def GetUrlCookieFile(url, quiet): |
| 517 | if url.startswith('persistent-'): | 529 | if url.startswith('persistent-'): |
| @@ -552,6 +564,7 @@ def GetUrlCookieFile(url, quiet): | |||
| 552 | cookiefile = os.path.expanduser(cookiefile) | 564 | cookiefile = os.path.expanduser(cookiefile) |
| 553 | yield cookiefile, None | 565 | yield cookiefile, None |
| 554 | 566 | ||
| 567 | |||
| 555 | def _preconnect(url): | 568 | def _preconnect(url): |
| 556 | m = URI_ALL.match(url) | 569 | m = URI_ALL.match(url) |
| 557 | if m: | 570 | if m: |
| @@ -572,9 +585,11 @@ def _preconnect(url): | |||
| 572 | 585 | ||
| 573 | return False | 586 | return False |
| 574 | 587 | ||
| 588 | |||
| 575 | class Remote(object): | 589 | class Remote(object): |
| 576 | """Configuration options related to a remote. | 590 | """Configuration options related to a remote. |
| 577 | """ | 591 | """ |
| 592 | |||
| 578 | def __init__(self, config, name): | 593 | def __init__(self, config, name): |
| 579 | self._config = config | 594 | self._config = config |
| 580 | self.name = name | 595 | self.name = name |
| @@ -735,6 +750,7 @@ class Remote(object): | |||
| 735 | class Branch(object): | 750 | class Branch(object): |
| 736 | """Configuration options related to a single branch. | 751 | """Configuration options related to a single branch. |
| 737 | """ | 752 | """ |
| 753 | |||
| 738 | def __init__(self, config, name): | 754 | def __init__(self, config, name): |
| 739 | self._config = config | 755 | self._config = config |
| 740 | self.name = name | 756 | self.name = name |
diff --git a/gitc_utils.py b/gitc_utils.py index 45920b07..11284e20 100644 --- a/gitc_utils.py +++ b/gitc_utils.py | |||
| @@ -29,12 +29,15 @@ from error import ManifestParseError | |||
| 29 | 29 | ||
| 30 | NUM_BATCH_RETRIEVE_REVISIONID = 32 | 30 | NUM_BATCH_RETRIEVE_REVISIONID = 32 |
| 31 | 31 | ||
| 32 | |||
| 32 | def get_gitc_manifest_dir(): | 33 | def get_gitc_manifest_dir(): |
| 33 | return wrapper.Wrapper().get_gitc_manifest_dir() | 34 | return wrapper.Wrapper().get_gitc_manifest_dir() |
| 34 | 35 | ||
| 36 | |||
| 35 | def parse_clientdir(gitc_fs_path): | 37 | def parse_clientdir(gitc_fs_path): |
| 36 | return wrapper.Wrapper().gitc_parse_clientdir(gitc_fs_path) | 38 | return wrapper.Wrapper().gitc_parse_clientdir(gitc_fs_path) |
| 37 | 39 | ||
| 40 | |||
| 38 | def _set_project_revisions(projects): | 41 | def _set_project_revisions(projects): |
| 39 | """Sets the revisionExpr for a list of projects. | 42 | """Sets the revisionExpr for a list of projects. |
| 40 | 43 | ||
| @@ -63,6 +66,7 @@ def _set_project_revisions(projects): | |||
| 63 | (proj.remote.url, proj.revisionExpr)) | 66 | (proj.remote.url, proj.revisionExpr)) |
| 64 | proj.revisionExpr = revisionExpr | 67 | proj.revisionExpr = revisionExpr |
| 65 | 68 | ||
| 69 | |||
| 66 | def _manifest_groups(manifest): | 70 | def _manifest_groups(manifest): |
| 67 | """Returns the manifest group string that should be synced | 71 | """Returns the manifest group string that should be synced |
| 68 | 72 | ||
| @@ -77,6 +81,7 @@ def _manifest_groups(manifest): | |||
| 77 | groups = 'default,platform-' + platform.system().lower() | 81 | groups = 'default,platform-' + platform.system().lower() |
| 78 | return groups | 82 | return groups |
| 79 | 83 | ||
| 84 | |||
| 80 | def generate_gitc_manifest(gitc_manifest, manifest, paths=None): | 85 | def generate_gitc_manifest(gitc_manifest, manifest, paths=None): |
| 81 | """Generate a manifest for shafsd to use for this GITC client. | 86 | """Generate a manifest for shafsd to use for this GITC client. |
| 82 | 87 | ||
| @@ -140,6 +145,7 @@ def generate_gitc_manifest(gitc_manifest, manifest, paths=None): | |||
| 140 | # Save the manifest. | 145 | # Save the manifest. |
| 141 | save_manifest(manifest) | 146 | save_manifest(manifest) |
| 142 | 147 | ||
| 148 | |||
| 143 | def save_manifest(manifest, client_dir=None): | 149 | def save_manifest(manifest, client_dir=None): |
| 144 | """Save the manifest file in the client_dir. | 150 | """Save the manifest file in the client_dir. |
| 145 | 151 | ||
| @@ -101,6 +101,7 @@ global_options.add_option('--event-log', | |||
| 101 | dest='event_log', action='store', | 101 | dest='event_log', action='store', |
| 102 | help='filename of event log to append timeline to') | 102 | help='filename of event log to append timeline to') |
| 103 | 103 | ||
| 104 | |||
| 104 | class _Repo(object): | 105 | class _Repo(object): |
| 105 | def __init__(self, repodir): | 106 | def __init__(self, repodir): |
| 106 | self.repodir = repodir | 107 | self.repodir = repodir |
| @@ -300,11 +301,13 @@ repo: error: | |||
| 300 | cp %s %s | 301 | cp %s %s |
| 301 | """ % (exp_str, WrapperPath(), repo_path), file=sys.stderr) | 302 | """ % (exp_str, WrapperPath(), repo_path), file=sys.stderr) |
| 302 | 303 | ||
| 304 | |||
| 303 | def _CheckRepoDir(repo_dir): | 305 | def _CheckRepoDir(repo_dir): |
| 304 | if not repo_dir: | 306 | if not repo_dir: |
| 305 | print('no --repo-dir argument', file=sys.stderr) | 307 | print('no --repo-dir argument', file=sys.stderr) |
| 306 | sys.exit(1) | 308 | sys.exit(1) |
| 307 | 309 | ||
| 310 | |||
| 308 | def _PruneOptions(argv, opt): | 311 | def _PruneOptions(argv, opt): |
| 309 | i = 0 | 312 | i = 0 |
| 310 | while i < len(argv): | 313 | while i < len(argv): |
| @@ -320,6 +323,7 @@ def _PruneOptions(argv, opt): | |||
| 320 | continue | 323 | continue |
| 321 | i += 1 | 324 | i += 1 |
| 322 | 325 | ||
| 326 | |||
| 323 | class _UserAgentHandler(urllib.request.BaseHandler): | 327 | class _UserAgentHandler(urllib.request.BaseHandler): |
| 324 | def http_request(self, req): | 328 | def http_request(self, req): |
| 325 | req.add_header('User-Agent', user_agent.repo) | 329 | req.add_header('User-Agent', user_agent.repo) |
| @@ -329,6 +333,7 @@ class _UserAgentHandler(urllib.request.BaseHandler): | |||
| 329 | req.add_header('User-Agent', user_agent.repo) | 333 | req.add_header('User-Agent', user_agent.repo) |
| 330 | return req | 334 | return req |
| 331 | 335 | ||
| 336 | |||
| 332 | def _AddPasswordFromUserInput(handler, msg, req): | 337 | def _AddPasswordFromUserInput(handler, msg, req): |
| 333 | # If repo could not find auth info from netrc, try to get it from user input | 338 | # If repo could not find auth info from netrc, try to get it from user input |
| 334 | url = req.get_full_url() | 339 | url = req.get_full_url() |
| @@ -342,6 +347,7 @@ def _AddPasswordFromUserInput(handler, msg, req): | |||
| 342 | return | 347 | return |
| 343 | handler.passwd.add_password(None, url, user, password) | 348 | handler.passwd.add_password(None, url, user, password) |
| 344 | 349 | ||
| 350 | |||
| 345 | class _BasicAuthHandler(urllib.request.HTTPBasicAuthHandler): | 351 | class _BasicAuthHandler(urllib.request.HTTPBasicAuthHandler): |
| 346 | def http_error_401(self, req, fp, code, msg, headers): | 352 | def http_error_401(self, req, fp, code, msg, headers): |
| 347 | _AddPasswordFromUserInput(self, msg, req) | 353 | _AddPasswordFromUserInput(self, msg, req) |
| @@ -351,6 +357,7 @@ class _BasicAuthHandler(urllib.request.HTTPBasicAuthHandler): | |||
| 351 | def http_error_auth_reqed(self, authreq, host, req, headers): | 357 | def http_error_auth_reqed(self, authreq, host, req, headers): |
| 352 | try: | 358 | try: |
| 353 | old_add_header = req.add_header | 359 | old_add_header = req.add_header |
| 360 | |||
| 354 | def _add_header(name, val): | 361 | def _add_header(name, val): |
| 355 | val = val.replace('\n', '') | 362 | val = val.replace('\n', '') |
| 356 | old_add_header(name, val) | 363 | old_add_header(name, val) |
| @@ -365,6 +372,7 @@ class _BasicAuthHandler(urllib.request.HTTPBasicAuthHandler): | |||
| 365 | self.retried = 0 | 372 | self.retried = 0 |
| 366 | raise | 373 | raise |
| 367 | 374 | ||
| 375 | |||
| 368 | class _DigestAuthHandler(urllib.request.HTTPDigestAuthHandler): | 376 | class _DigestAuthHandler(urllib.request.HTTPDigestAuthHandler): |
| 369 | def http_error_401(self, req, fp, code, msg, headers): | 377 | def http_error_401(self, req, fp, code, msg, headers): |
| 370 | _AddPasswordFromUserInput(self, msg, req) | 378 | _AddPasswordFromUserInput(self, msg, req) |
| @@ -374,6 +382,7 @@ class _DigestAuthHandler(urllib.request.HTTPDigestAuthHandler): | |||
| 374 | def http_error_auth_reqed(self, auth_header, host, req, headers): | 382 | def http_error_auth_reqed(self, auth_header, host, req, headers): |
| 375 | try: | 383 | try: |
| 376 | old_add_header = req.add_header | 384 | old_add_header = req.add_header |
| 385 | |||
| 377 | def _add_header(name, val): | 386 | def _add_header(name, val): |
| 378 | val = val.replace('\n', '') | 387 | val = val.replace('\n', '') |
| 379 | old_add_header(name, val) | 388 | old_add_header(name, val) |
| @@ -388,6 +397,7 @@ class _DigestAuthHandler(urllib.request.HTTPDigestAuthHandler): | |||
| 388 | self.retried = 0 | 397 | self.retried = 0 |
| 389 | raise | 398 | raise |
| 390 | 399 | ||
| 400 | |||
| 391 | class _KerberosAuthHandler(urllib.request.BaseHandler): | 401 | class _KerberosAuthHandler(urllib.request.BaseHandler): |
| 392 | def __init__(self): | 402 | def __init__(self): |
| 393 | self.retried = 0 | 403 | self.retried = 0 |
| @@ -468,6 +478,7 @@ class _KerberosAuthHandler(urllib.request.BaseHandler): | |||
| 468 | kerberos.authGSSClientClean(self.context) | 478 | kerberos.authGSSClientClean(self.context) |
| 469 | self.context = None | 479 | self.context = None |
| 470 | 480 | ||
| 481 | |||
| 471 | def init_http(): | 482 | def init_http(): |
| 472 | handlers = [_UserAgentHandler()] | 483 | handlers = [_UserAgentHandler()] |
| 473 | 484 | ||
| @@ -495,6 +506,7 @@ def init_http(): | |||
| 495 | handlers.append(urllib.request.HTTPSHandler(debuglevel=1)) | 506 | handlers.append(urllib.request.HTTPSHandler(debuglevel=1)) |
| 496 | urllib.request.install_opener(urllib.request.build_opener(*handlers)) | 507 | urllib.request.install_opener(urllib.request.build_opener(*handlers)) |
| 497 | 508 | ||
| 509 | |||
| 498 | def _Main(argv): | 510 | def _Main(argv): |
| 499 | result = 0 | 511 | result = 0 |
| 500 | 512 | ||
| @@ -551,5 +563,6 @@ def _Main(argv): | |||
| 551 | TerminatePager() | 563 | TerminatePager() |
| 552 | sys.exit(result) | 564 | sys.exit(result) |
| 553 | 565 | ||
| 566 | |||
| 554 | if __name__ == '__main__': | 567 | if __name__ == '__main__': |
| 555 | _Main(sys.argv[1:]) | 568 | _Main(sys.argv[1:]) |
diff --git a/manifest_xml.py b/manifest_xml.py index fd0e4f12..7f38d8c3 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
| @@ -56,6 +56,7 @@ urllib.parse.uses_netloc.extend([ | |||
| 56 | 'sso', | 56 | 'sso', |
| 57 | 'rpc']) | 57 | 'rpc']) |
| 58 | 58 | ||
| 59 | |||
| 59 | class _Default(object): | 60 | class _Default(object): |
| 60 | """Project defaults within the manifest.""" | 61 | """Project defaults within the manifest.""" |
| 61 | 62 | ||
| @@ -74,6 +75,7 @@ class _Default(object): | |||
| 74 | def __ne__(self, other): | 75 | def __ne__(self, other): |
| 75 | return self.__dict__ != other.__dict__ | 76 | return self.__dict__ != other.__dict__ |
| 76 | 77 | ||
| 78 | |||
| 77 | class _XmlRemote(object): | 79 | class _XmlRemote(object): |
| 78 | def __init__(self, | 80 | def __init__(self, |
| 79 | name, | 81 | name, |
| @@ -127,6 +129,7 @@ class _XmlRemote(object): | |||
| 127 | orig_name=self.name, | 129 | orig_name=self.name, |
| 128 | fetchUrl=self.fetchUrl) | 130 | fetchUrl=self.fetchUrl) |
| 129 | 131 | ||
| 132 | |||
| 130 | class XmlManifest(object): | 133 | class XmlManifest(object): |
| 131 | """manages the repo configuration file""" | 134 | """manages the repo configuration file""" |
| 132 | 135 | ||
| @@ -655,7 +658,6 @@ class XmlManifest(object): | |||
| 655 | if self._repo_hooks_project and (self._repo_hooks_project.name == name): | 658 | if self._repo_hooks_project and (self._repo_hooks_project.name == name): |
| 656 | self._repo_hooks_project = None | 659 | self._repo_hooks_project = None |
| 657 | 660 | ||
| 658 | |||
| 659 | def _AddMetaProjectMirror(self, m): | 661 | def _AddMetaProjectMirror(self, m): |
| 660 | name = None | 662 | name = None |
| 661 | m_url = m.GetRemote(m.remote.name).url | 663 | m_url = m.GetRemote(m.remote.name).url |
| @@ -27,6 +27,7 @@ pager_process = None | |||
| 27 | old_stdout = None | 27 | old_stdout = None |
| 28 | old_stderr = None | 28 | old_stderr = None |
| 29 | 29 | ||
| 30 | |||
| 30 | def RunPager(globalConfig): | 31 | def RunPager(globalConfig): |
| 31 | if not os.isatty(0) or not os.isatty(1): | 32 | if not os.isatty(0) or not os.isatty(1): |
| 32 | return | 33 | return |
| @@ -39,6 +40,7 @@ def RunPager(globalConfig): | |||
| 39 | else: | 40 | else: |
| 40 | _ForkPager(pager) | 41 | _ForkPager(pager) |
| 41 | 42 | ||
| 43 | |||
| 42 | def TerminatePager(): | 44 | def TerminatePager(): |
| 43 | global pager_process, old_stdout, old_stderr | 45 | global pager_process, old_stdout, old_stderr |
| 44 | if pager_process: | 46 | if pager_process: |
| @@ -52,6 +54,7 @@ def TerminatePager(): | |||
| 52 | sys.stdout = old_stdout | 54 | sys.stdout = old_stdout |
| 53 | sys.stderr = old_stderr | 55 | sys.stderr = old_stderr |
| 54 | 56 | ||
| 57 | |||
| 55 | def _PipePager(pager): | 58 | def _PipePager(pager): |
| 56 | global pager_process, old_stdout, old_stderr | 59 | global pager_process, old_stdout, old_stderr |
| 57 | assert pager_process is None, "Only one active pager process at a time" | 60 | assert pager_process is None, "Only one active pager process at a time" |
| @@ -62,6 +65,7 @@ def _PipePager(pager): | |||
| 62 | sys.stdout = pager_process.stdin | 65 | sys.stdout = pager_process.stdin |
| 63 | sys.stderr = pager_process.stdin | 66 | sys.stderr = pager_process.stdin |
| 64 | 67 | ||
| 68 | |||
| 65 | def _ForkPager(pager): | 69 | def _ForkPager(pager): |
| 66 | global active | 70 | global active |
| 67 | # This process turns into the pager; a child it forks will | 71 | # This process turns into the pager; a child it forks will |
| @@ -88,6 +92,7 @@ def _ForkPager(pager): | |||
| 88 | print("fatal: cannot start pager '%s'" % pager, file=sys.stderr) | 92 | print("fatal: cannot start pager '%s'" % pager, file=sys.stderr) |
| 89 | sys.exit(255) | 93 | sys.exit(255) |
| 90 | 94 | ||
| 95 | |||
| 91 | def _SelectPager(globalConfig): | 96 | def _SelectPager(globalConfig): |
| 92 | try: | 97 | try: |
| 93 | return os.environ['GIT_PAGER'] | 98 | return os.environ['GIT_PAGER'] |
| @@ -105,6 +110,7 @@ def _SelectPager(globalConfig): | |||
| 105 | 110 | ||
| 106 | return 'less' | 111 | return 'less' |
| 107 | 112 | ||
| 113 | |||
| 108 | def _BecomePager(pager): | 114 | def _BecomePager(pager): |
| 109 | # Delaying execution of the pager until we have output | 115 | # Delaying execution of the pager until we have output |
| 110 | # ready works around a long-standing bug in popularly | 116 | # ready works around a long-standing bug in popularly |
diff --git a/platform_utils.py b/platform_utils.py index 06ef9b18..490ba208 100644 --- a/platform_utils.py +++ b/platform_utils.py | |||
| @@ -92,6 +92,7 @@ class _FileDescriptorStreamsNonBlocking(FileDescriptorStreams): | |||
| 92 | """ | 92 | """ |
| 93 | class Stream(object): | 93 | class Stream(object): |
| 94 | """ Encapsulates a file descriptor """ | 94 | """ Encapsulates a file descriptor """ |
| 95 | |||
| 95 | def __init__(self, fd, dest, std_name): | 96 | def __init__(self, fd, dest, std_name): |
| 96 | self.fd = fd | 97 | self.fd = fd |
| 97 | self.dest = dest | 98 | self.dest = dest |
| @@ -125,6 +126,7 @@ class _FileDescriptorStreamsThreads(FileDescriptorStreams): | |||
| 125 | non blocking I/O. This implementation requires creating threads issuing | 126 | non blocking I/O. This implementation requires creating threads issuing |
| 126 | blocking read operations on file descriptors. | 127 | blocking read operations on file descriptors. |
| 127 | """ | 128 | """ |
| 129 | |||
| 128 | def __init__(self): | 130 | def __init__(self): |
| 129 | super(_FileDescriptorStreamsThreads, self).__init__() | 131 | super(_FileDescriptorStreamsThreads, self).__init__() |
| 130 | # The queue is shared accross all threads so we can simulate the | 132 | # The queue is shared accross all threads so we can simulate the |
| @@ -144,12 +146,14 @@ class _FileDescriptorStreamsThreads(FileDescriptorStreams): | |||
| 144 | 146 | ||
| 145 | class QueueItem(object): | 147 | class QueueItem(object): |
| 146 | """ Item put in the shared queue """ | 148 | """ Item put in the shared queue """ |
| 149 | |||
| 147 | def __init__(self, stream, data): | 150 | def __init__(self, stream, data): |
| 148 | self.stream = stream | 151 | self.stream = stream |
| 149 | self.data = data | 152 | self.data = data |
| 150 | 153 | ||
| 151 | class Stream(object): | 154 | class Stream(object): |
| 152 | """ Encapsulates a file descriptor """ | 155 | """ Encapsulates a file descriptor """ |
| 156 | |||
| 153 | def __init__(self, fd, dest, std_name, queue): | 157 | def __init__(self, fd, dest, std_name, queue): |
| 154 | self.fd = fd | 158 | self.fd = fd |
| 155 | self.dest = dest | 159 | self.dest = dest |
diff --git a/progress.py b/progress.py index 8a643db2..ff627980 100644 --- a/progress.py +++ b/progress.py | |||
| @@ -26,6 +26,7 @@ _NOT_TTY = not os.isatty(2) | |||
| 26 | # column 0. | 26 | # column 0. |
| 27 | CSI_ERASE_LINE = '\x1b[2K' | 27 | CSI_ERASE_LINE = '\x1b[2K' |
| 28 | 28 | ||
| 29 | |||
| 29 | class Progress(object): | 30 | class Progress(object): |
| 30 | def __init__(self, title, total=0, units='', print_newline=False, | 31 | def __init__(self, title, total=0, units='', print_newline=False, |
| 31 | always_print_percentage=False): | 32 | always_print_percentage=False): |
| @@ -85,6 +85,7 @@ def not_rev(r): | |||
| 85 | def sq(r): | 85 | def sq(r): |
| 86 | return "'" + r.replace("'", "'\''") + "'" | 86 | return "'" + r.replace("'", "'\''") + "'" |
| 87 | 87 | ||
| 88 | |||
| 88 | _project_hook_list = None | 89 | _project_hook_list = None |
| 89 | 90 | ||
| 90 | 91 | ||
| @@ -1256,9 +1257,7 @@ class Project(object): | |||
| 1256 | print(line[:-1]) | 1257 | print(line[:-1]) |
| 1257 | return p.Wait() == 0 | 1258 | return p.Wait() == 0 |
| 1258 | 1259 | ||
| 1259 | |||
| 1260 | # Publish / Upload ## | 1260 | # Publish / Upload ## |
| 1261 | |||
| 1262 | def WasPublished(self, branch, all_refs=None): | 1261 | def WasPublished(self, branch, all_refs=None): |
| 1263 | """Was the branch published (uploaded) for code review? | 1262 | """Was the branch published (uploaded) for code review? |
| 1264 | If so, returns the SHA-1 hash of the last published | 1263 | If so, returns the SHA-1 hash of the last published |
| @@ -1410,9 +1409,7 @@ class Project(object): | |||
| 1410 | R_HEADS + branch.name, | 1409 | R_HEADS + branch.name, |
| 1411 | message=msg) | 1410 | message=msg) |
| 1412 | 1411 | ||
| 1413 | |||
| 1414 | # Sync ## | 1412 | # Sync ## |
| 1415 | |||
| 1416 | def _ExtractArchive(self, tarpath, path=None): | 1413 | def _ExtractArchive(self, tarpath, path=None): |
| 1417 | """Extract the given tar on its current location | 1414 | """Extract the given tar on its current location |
| 1418 | 1415 | ||
| @@ -1819,9 +1816,7 @@ class Project(object): | |||
| 1819 | patch_id, | 1816 | patch_id, |
| 1820 | self.bare_git.rev_parse('FETCH_HEAD')) | 1817 | self.bare_git.rev_parse('FETCH_HEAD')) |
| 1821 | 1818 | ||
| 1822 | |||
| 1823 | # Branch Management ## | 1819 | # Branch Management ## |
| 1824 | |||
| 1825 | def GetHeadPath(self): | 1820 | def GetHeadPath(self): |
| 1826 | """Return the full path to the HEAD ref.""" | 1821 | """Return the full path to the HEAD ref.""" |
| 1827 | dotgit = os.path.join(self.worktree, '.git') | 1822 | dotgit = os.path.join(self.worktree, '.git') |
| @@ -2019,9 +2014,7 @@ class Project(object): | |||
| 2019 | kept.append(ReviewableBranch(self, branch, base)) | 2014 | kept.append(ReviewableBranch(self, branch, base)) |
| 2020 | return kept | 2015 | return kept |
| 2021 | 2016 | ||
| 2022 | |||
| 2023 | # Submodule Management ## | 2017 | # Submodule Management ## |
| 2024 | |||
| 2025 | def GetRegisteredSubprojects(self): | 2018 | def GetRegisteredSubprojects(self): |
| 2026 | result = [] | 2019 | result = [] |
| 2027 | 2020 | ||
| @@ -2172,7 +2165,6 @@ class Project(object): | |||
| 2172 | result.extend(subproject.GetDerivedSubprojects()) | 2165 | result.extend(subproject.GetDerivedSubprojects()) |
| 2173 | return result | 2166 | return result |
| 2174 | 2167 | ||
| 2175 | |||
| 2176 | # Direct Git Commands ## | 2168 | # Direct Git Commands ## |
| 2177 | def _CheckForImmutableRevision(self): | 2169 | def _CheckForImmutableRevision(self): |
| 2178 | try: | 2170 | try: |
diff --git a/pyversion.py b/pyversion.py index f6082408..8dbf909b 100644 --- a/pyversion.py +++ b/pyversion.py | |||
| @@ -16,5 +16,6 @@ | |||
| 16 | 16 | ||
| 17 | import sys | 17 | import sys |
| 18 | 18 | ||
| 19 | |||
| 19 | def is_python3(): | 20 | def is_python3(): |
| 20 | return sys.version_info[0] == 3 | 21 | return sys.version_info[0] == 3 |
diff --git a/repo_trace.py b/repo_trace.py index f5bc76d4..cd571f4c 100644 --- a/repo_trace.py +++ b/repo_trace.py | |||
| @@ -28,13 +28,16 @@ REPO_TRACE = 'REPO_TRACE' | |||
| 28 | 28 | ||
| 29 | _TRACE = os.environ.get(REPO_TRACE) == '1' | 29 | _TRACE = os.environ.get(REPO_TRACE) == '1' |
| 30 | 30 | ||
| 31 | |||
| 31 | def IsTrace(): | 32 | def IsTrace(): |
| 32 | return _TRACE | 33 | return _TRACE |
| 33 | 34 | ||
| 35 | |||
| 34 | def SetTrace(): | 36 | def SetTrace(): |
| 35 | global _TRACE | 37 | global _TRACE |
| 36 | _TRACE = True | 38 | _TRACE = True |
| 37 | 39 | ||
| 40 | |||
| 38 | def Trace(fmt, *args): | 41 | def Trace(fmt, *args): |
| 39 | if IsTrace(): | 42 | if IsTrace(): |
| 40 | print(fmt % args, file=sys.stderr) | 43 | print(fmt % args, file=sys.stderr) |
diff --git a/subcmds/abandon.py b/subcmds/abandon.py index 9a645c0a..f3478129 100644 --- a/subcmds/abandon.py +++ b/subcmds/abandon.py | |||
| @@ -21,6 +21,7 @@ from collections import defaultdict | |||
| 21 | from git_command import git | 21 | from git_command import git |
| 22 | from progress import Progress | 22 | from progress import Progress |
| 23 | 23 | ||
| 24 | |||
| 24 | class Abandon(Command): | 25 | class Abandon(Command): |
| 25 | common = True | 26 | common = True |
| 26 | helpSummary = "Permanently abandon a development branch" | 27 | helpSummary = "Permanently abandon a development branch" |
| @@ -32,6 +33,7 @@ deleting it (and all its history) from your local repository. | |||
| 32 | 33 | ||
| 33 | It is equivalent to "git branch -D <branchname>". | 34 | It is equivalent to "git branch -D <branchname>". |
| 34 | """ | 35 | """ |
| 36 | |||
| 35 | def _Options(self, p): | 37 | def _Options(self, p): |
| 36 | p.add_option('--all', | 38 | p.add_option('--all', |
| 37 | dest='all', action='store_true', | 39 | dest='all', action='store_true', |
diff --git a/subcmds/branches.py b/subcmds/branches.py index b4894ec8..9709f7f0 100644 --- a/subcmds/branches.py +++ b/subcmds/branches.py | |||
| @@ -19,6 +19,7 @@ import sys | |||
| 19 | from color import Coloring | 19 | from color import Coloring |
| 20 | from command import Command | 20 | from command import Command |
| 21 | 21 | ||
| 22 | |||
| 22 | class BranchColoring(Coloring): | 23 | class BranchColoring(Coloring): |
| 23 | def __init__(self, config): | 24 | def __init__(self, config): |
| 24 | Coloring.__init__(self, config, 'branch') | 25 | Coloring.__init__(self, config, 'branch') |
| @@ -26,6 +27,7 @@ class BranchColoring(Coloring): | |||
| 26 | self.local = self.printer('local') | 27 | self.local = self.printer('local') |
| 27 | self.notinproject = self.printer('notinproject', fg='red') | 28 | self.notinproject = self.printer('notinproject', fg='red') |
| 28 | 29 | ||
| 30 | |||
| 29 | class BranchInfo(object): | 31 | class BranchInfo(object): |
| 30 | def __init__(self, name): | 32 | def __init__(self, name): |
| 31 | self.name = name | 33 | self.name = name |
diff --git a/subcmds/checkout.py b/subcmds/checkout.py index c8a09a8e..efa31d26 100644 --- a/subcmds/checkout.py +++ b/subcmds/checkout.py | |||
| @@ -19,6 +19,7 @@ import sys | |||
| 19 | from command import Command | 19 | from command import Command |
| 20 | from progress import Progress | 20 | from progress import Progress |
| 21 | 21 | ||
| 22 | |||
| 22 | class Checkout(Command): | 23 | class Checkout(Command): |
| 23 | common = True | 24 | common = True |
| 24 | helpSummary = "Checkout a branch for development" | 25 | helpSummary = "Checkout a branch for development" |
diff --git a/subcmds/cherry_pick.py b/subcmds/cherry_pick.py index 8d81be33..3ad82109 100644 --- a/subcmds/cherry_pick.py +++ b/subcmds/cherry_pick.py | |||
| @@ -22,6 +22,7 @@ from git_command import GitCommand | |||
| 22 | 22 | ||
| 23 | CHANGE_ID_RE = re.compile(r'^\s*Change-Id: I([0-9a-f]{40})\s*$') | 23 | CHANGE_ID_RE = re.compile(r'^\s*Change-Id: I([0-9a-f]{40})\s*$') |
| 24 | 24 | ||
| 25 | |||
| 25 | class CherryPick(Command): | 26 | class CherryPick(Command): |
| 26 | common = True | 27 | common = True |
| 27 | helpSummary = "Cherry-pick a change." | 28 | helpSummary = "Cherry-pick a change." |
diff --git a/subcmds/diff.py b/subcmds/diff.py index fa41e70e..406baa28 100644 --- a/subcmds/diff.py +++ b/subcmds/diff.py | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | from command import PagedCommand | 17 | from command import PagedCommand |
| 18 | 18 | ||
| 19 | |||
| 19 | class Diff(PagedCommand): | 20 | class Diff(PagedCommand): |
| 20 | common = True | 21 | common = True |
| 21 | helpSummary = "Show changes between commit and working tree" | 22 | helpSummary = "Show changes between commit and working tree" |
diff --git a/subcmds/diffmanifests.py b/subcmds/diffmanifests.py index 9bdb5e14..77f99df2 100644 --- a/subcmds/diffmanifests.py +++ b/subcmds/diffmanifests.py | |||
| @@ -18,10 +18,12 @@ from color import Coloring | |||
| 18 | from command import PagedCommand | 18 | from command import PagedCommand |
| 19 | from manifest_xml import XmlManifest | 19 | from manifest_xml import XmlManifest |
| 20 | 20 | ||
| 21 | |||
| 21 | class _Coloring(Coloring): | 22 | class _Coloring(Coloring): |
| 22 | def __init__(self, config): | 23 | def __init__(self, config): |
| 23 | Coloring.__init__(self, config, "status") | 24 | Coloring.__init__(self, config, "status") |
| 24 | 25 | ||
| 26 | |||
| 25 | class Diffmanifests(PagedCommand): | 27 | class Diffmanifests(PagedCommand): |
| 26 | """ A command to see logs in projects represented by manifests | 28 | """ A command to see logs in projects represented by manifests |
| 27 | 29 | ||
diff --git a/subcmds/download.py b/subcmds/download.py index fbd302aa..87d0ce04 100644 --- a/subcmds/download.py +++ b/subcmds/download.py | |||
| @@ -23,6 +23,7 @@ from error import GitError | |||
| 23 | 23 | ||
| 24 | CHANGE_RE = re.compile(r'^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$') | 24 | CHANGE_RE = re.compile(r'^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$') |
| 25 | 25 | ||
| 26 | |||
| 26 | class Download(Command): | 27 | class Download(Command): |
| 27 | common = True | 28 | common = True |
| 28 | helpSummary = "Download and checkout a change" | 29 | helpSummary = "Download and checkout a change" |
diff --git a/subcmds/forall.py b/subcmds/forall.py index 5d2be91f..dbf26f0b 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py | |||
| @@ -277,6 +277,7 @@ without iterating through the remaining projects. | |||
| 277 | return | 277 | return |
| 278 | yield [mirror, opt, cmd, shell, cnt, config, project] | 278 | yield [mirror, opt, cmd, shell, cnt, config, project] |
| 279 | 279 | ||
| 280 | |||
| 280 | class WorkerKeyboardInterrupt(Exception): | 281 | class WorkerKeyboardInterrupt(Exception): |
| 281 | """ Keyboard interrupt exception for worker processes. """ | 282 | """ Keyboard interrupt exception for worker processes. """ |
| 282 | pass | 283 | pass |
| @@ -285,6 +286,7 @@ class WorkerKeyboardInterrupt(Exception): | |||
| 285 | def InitWorker(): | 286 | def InitWorker(): |
| 286 | signal.signal(signal.SIGINT, signal.SIG_IGN) | 287 | signal.signal(signal.SIGINT, signal.SIG_IGN) |
| 287 | 288 | ||
| 289 | |||
| 288 | def DoWorkWrapper(args): | 290 | def DoWorkWrapper(args): |
| 289 | """ A wrapper around the DoWork() method. | 291 | """ A wrapper around the DoWork() method. |
| 290 | 292 | ||
| @@ -303,6 +305,7 @@ def DoWorkWrapper(args): | |||
| 303 | 305 | ||
| 304 | def DoWork(project, mirror, opt, cmd, shell, cnt, config): | 306 | def DoWork(project, mirror, opt, cmd, shell, cnt, config): |
| 305 | env = os.environ.copy() | 307 | env = os.environ.copy() |
| 308 | |||
| 306 | def setenv(name, val): | 309 | def setenv(name, val): |
| 307 | if val is None: | 310 | if val is None: |
| 308 | val = '' | 311 | val = '' |
diff --git a/subcmds/gitc_delete.py b/subcmds/gitc_delete.py index e5214b8e..1011276f 100644 --- a/subcmds/gitc_delete.py +++ b/subcmds/gitc_delete.py | |||
| @@ -24,6 +24,7 @@ from pyversion import is_python3 | |||
| 24 | if not is_python3(): | 24 | if not is_python3(): |
| 25 | input = raw_input | 25 | input = raw_input |
| 26 | 26 | ||
| 27 | |||
| 27 | class GitcDelete(Command, GitcClientCommand): | 28 | class GitcDelete(Command, GitcClientCommand): |
| 28 | common = True | 29 | common = True |
| 29 | visible_everywhere = False | 30 | visible_everywhere = False |
diff --git a/subcmds/grep.py b/subcmds/grep.py index 4dd85d57..13069286 100644 --- a/subcmds/grep.py +++ b/subcmds/grep.py | |||
| @@ -23,12 +23,14 @@ from command import PagedCommand | |||
| 23 | from error import GitError | 23 | from error import GitError |
| 24 | from git_command import git_require, GitCommand | 24 | from git_command import git_require, GitCommand |
| 25 | 25 | ||
| 26 | |||
| 26 | class GrepColoring(Coloring): | 27 | class GrepColoring(Coloring): |
| 27 | def __init__(self, config): | 28 | def __init__(self, config): |
| 28 | Coloring.__init__(self, config, 'grep') | 29 | Coloring.__init__(self, config, 'grep') |
| 29 | self.project = self.printer('project', attr='bold') | 30 | self.project = self.printer('project', attr='bold') |
| 30 | self.fail = self.printer('fail', fg='red') | 31 | self.fail = self.printer('fail', fg='red') |
| 31 | 32 | ||
| 33 | |||
| 32 | class Grep(PagedCommand): | 34 | class Grep(PagedCommand): |
| 33 | common = True | 35 | common = True |
| 34 | helpSummary = "Print lines matching a pattern" | 36 | helpSummary = "Print lines matching a pattern" |
| @@ -156,7 +158,6 @@ contain a line that matches both expressions: | |||
| 156 | action='callback', callback=carry, | 158 | action='callback', callback=carry, |
| 157 | help='Show only file names not containing matching lines') | 159 | help='Show only file names not containing matching lines') |
| 158 | 160 | ||
| 159 | |||
| 160 | def Execute(self, opt, args): | 161 | def Execute(self, opt, args): |
| 161 | out = GrepColoring(self.manifest.manifestProject.config) | 162 | out = GrepColoring(self.manifest.manifestProject.config) |
| 162 | 163 | ||
diff --git a/subcmds/help.py b/subcmds/help.py index 93b9a86d..36b3a7ae 100644 --- a/subcmds/help.py +++ b/subcmds/help.py | |||
| @@ -23,6 +23,7 @@ from color import Coloring | |||
| 23 | from command import PagedCommand, MirrorSafeCommand, GitcAvailableCommand, GitcClientCommand | 23 | from command import PagedCommand, MirrorSafeCommand, GitcAvailableCommand, GitcClientCommand |
| 24 | import gitc_utils | 24 | import gitc_utils |
| 25 | 25 | ||
| 26 | |||
| 26 | class Help(PagedCommand, MirrorSafeCommand): | 27 | class Help(PagedCommand, MirrorSafeCommand): |
| 27 | common = False | 28 | common = False |
| 28 | helpSummary = "Display detailed help on a command" | 29 | helpSummary = "Display detailed help on a command" |
diff --git a/subcmds/info.py b/subcmds/info.py index 96fa6a4c..76f5d1d6 100644 --- a/subcmds/info.py +++ b/subcmds/info.py | |||
| @@ -18,10 +18,12 @@ from command import PagedCommand | |||
| 18 | from color import Coloring | 18 | from color import Coloring |
| 19 | from git_refs import R_M | 19 | from git_refs import R_M |
| 20 | 20 | ||
| 21 | |||
| 21 | class _Coloring(Coloring): | 22 | class _Coloring(Coloring): |
| 22 | def __init__(self, config): | 23 | def __init__(self, config): |
| 23 | Coloring.__init__(self, config, "status") | 24 | Coloring.__init__(self, config, "status") |
| 24 | 25 | ||
| 26 | |||
| 25 | class Info(PagedCommand): | 27 | class Info(PagedCommand): |
| 26 | common = True | 28 | common = True |
| 27 | helpSummary = "Get info on the manifest branch, current branch or unmerged branches" | 29 | helpSummary = "Get info on the manifest branch, current branch or unmerged branches" |
| @@ -41,7 +43,6 @@ class Info(PagedCommand): | |||
| 41 | dest="local", action="store_true", | 43 | dest="local", action="store_true", |
| 42 | help="Disable all remote operations") | 44 | help="Disable all remote operations") |
| 43 | 45 | ||
| 44 | |||
| 45 | def Execute(self, opt, args): | 46 | def Execute(self, opt, args): |
| 46 | self.out = _Coloring(self.manifest.globalConfig) | 47 | self.out = _Coloring(self.manifest.globalConfig) |
| 47 | self.heading = self.out.printer('heading', attr='bold') | 48 | self.heading = self.out.printer('heading', attr='bold') |
diff --git a/subcmds/init.py b/subcmds/init.py index 7181b86f..dde97286 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
| @@ -37,6 +37,7 @@ from git_config import GitConfig | |||
| 37 | from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD | 37 | from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD |
| 38 | import platform_utils | 38 | import platform_utils |
| 39 | 39 | ||
| 40 | |||
| 40 | class Init(InteractiveCommand, MirrorSafeCommand): | 41 | class Init(InteractiveCommand, MirrorSafeCommand): |
| 41 | common = True | 42 | common = True |
| 42 | helpSummary = "Initialize repo in the current directory" | 43 | helpSummary = "Initialize repo in the current directory" |
diff --git a/subcmds/list.py b/subcmds/list.py index 1cd971ef..13cae5ff 100644 --- a/subcmds/list.py +++ b/subcmds/list.py | |||
| @@ -18,6 +18,7 @@ from __future__ import print_function | |||
| 18 | 18 | ||
| 19 | from command import Command, MirrorSafeCommand | 19 | from command import Command, MirrorSafeCommand |
| 20 | 20 | ||
| 21 | |||
| 21 | class List(Command, MirrorSafeCommand): | 22 | class List(Command, MirrorSafeCommand): |
| 22 | common = True | 23 | common = True |
| 23 | helpSummary = "List projects and their associated directories" | 24 | helpSummary = "List projects and their associated directories" |
diff --git a/subcmds/manifest.py b/subcmds/manifest.py index 6bb01045..072c9ff7 100644 --- a/subcmds/manifest.py +++ b/subcmds/manifest.py | |||
| @@ -20,6 +20,7 @@ import sys | |||
| 20 | 20 | ||
| 21 | from command import PagedCommand | 21 | from command import PagedCommand |
| 22 | 22 | ||
| 23 | |||
| 23 | class Manifest(PagedCommand): | 24 | class Manifest(PagedCommand): |
| 24 | common = False | 25 | common = False |
| 25 | helpSummary = "Manifest inspection utility" | 26 | helpSummary = "Manifest inspection utility" |
diff --git a/subcmds/prune.py b/subcmds/prune.py index ff2fba1d..e90ff213 100644 --- a/subcmds/prune.py +++ b/subcmds/prune.py | |||
| @@ -18,6 +18,7 @@ from __future__ import print_function | |||
| 18 | from color import Coloring | 18 | from color import Coloring |
| 19 | from command import PagedCommand | 19 | from command import PagedCommand |
| 20 | 20 | ||
| 21 | |||
| 21 | class Prune(PagedCommand): | 22 | class Prune(PagedCommand): |
| 22 | common = True | 23 | common = True |
| 23 | helpSummary = "Prune (delete) already merged topics" | 24 | helpSummary = "Prune (delete) already merged topics" |
diff --git a/subcmds/selfupdate.py b/subcmds/selfupdate.py index b157e2f1..4817a862 100644 --- a/subcmds/selfupdate.py +++ b/subcmds/selfupdate.py | |||
| @@ -22,6 +22,7 @@ from command import Command, MirrorSafeCommand | |||
| 22 | from subcmds.sync import _PostRepoUpgrade | 22 | from subcmds.sync import _PostRepoUpgrade |
| 23 | from subcmds.sync import _PostRepoFetch | 23 | from subcmds.sync import _PostRepoFetch |
| 24 | 24 | ||
| 25 | |||
| 25 | class Selfupdate(Command, MirrorSafeCommand): | 26 | class Selfupdate(Command, MirrorSafeCommand): |
| 26 | common = False | 27 | common = False |
| 27 | helpSummary = "Update repo to the latest version" | 28 | helpSummary = "Update repo to the latest version" |
diff --git a/subcmds/smartsync.py b/subcmds/smartsync.py index 675b9834..6037e5a3 100644 --- a/subcmds/smartsync.py +++ b/subcmds/smartsync.py | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | from subcmds.sync import Sync | 17 | from subcmds.sync import Sync |
| 18 | 18 | ||
| 19 | |||
| 19 | class Smartsync(Sync): | 20 | class Smartsync(Sync): |
| 20 | common = True | 21 | common = True |
| 21 | helpSummary = "Update working tree to the latest known good revision" | 22 | helpSummary = "Update working tree to the latest known good revision" |
diff --git a/subcmds/stage.py b/subcmds/stage.py index aeb49513..4dce5ce5 100644 --- a/subcmds/stage.py +++ b/subcmds/stage.py | |||
| @@ -21,6 +21,7 @@ from color import Coloring | |||
| 21 | from command import InteractiveCommand | 21 | from command import InteractiveCommand |
| 22 | from git_command import GitCommand | 22 | from git_command import GitCommand |
| 23 | 23 | ||
| 24 | |||
| 24 | class _ProjectList(Coloring): | 25 | class _ProjectList(Coloring): |
| 25 | def __init__(self, gc): | 26 | def __init__(self, gc): |
| 26 | Coloring.__init__(self, gc, 'interactive') | 27 | Coloring.__init__(self, gc, 'interactive') |
| @@ -28,6 +29,7 @@ class _ProjectList(Coloring): | |||
| 28 | self.header = self.printer('header', attr='bold') | 29 | self.header = self.printer('header', attr='bold') |
| 29 | self.help = self.printer('help', fg='red', attr='bold') | 30 | self.help = self.printer('help', fg='red', attr='bold') |
| 30 | 31 | ||
| 32 | |||
| 31 | class Stage(InteractiveCommand): | 33 | class Stage(InteractiveCommand): |
| 32 | common = True | 34 | common = True |
| 33 | helpSummary = "Stage file(s) for commit" | 35 | helpSummary = "Stage file(s) for commit" |
| @@ -105,6 +107,7 @@ The '%prog' command stages files to prepare the next commit. | |||
| 105 | continue | 107 | continue |
| 106 | print('Bye.') | 108 | print('Bye.') |
| 107 | 109 | ||
| 110 | |||
| 108 | def _AddI(project): | 111 | def _AddI(project): |
| 109 | p = GitCommand(project, ['add', '--interactive'], bare=False) | 112 | p = GitCommand(project, ['add', '--interactive'], bare=False) |
| 110 | p.Wait() | 113 | p.Wait() |
diff --git a/subcmds/start.py b/subcmds/start.py index f98f790a..adc6d293 100644 --- a/subcmds/start.py +++ b/subcmds/start.py | |||
| @@ -25,6 +25,7 @@ import gitc_utils | |||
| 25 | from progress import Progress | 25 | from progress import Progress |
| 26 | from project import SyncBuffer | 26 | from project import SyncBuffer |
| 27 | 27 | ||
| 28 | |||
| 28 | class Start(Command): | 29 | class Start(Command): |
| 29 | common = True | 30 | common = True |
| 30 | helpSummary = "Start a new branch for development" | 31 | helpSummary = "Start a new branch for development" |
diff --git a/subcmds/status.py b/subcmds/status.py index a04ba922..b594bd89 100644 --- a/subcmds/status.py +++ b/subcmds/status.py | |||
| @@ -31,6 +31,7 @@ import os | |||
| 31 | from color import Coloring | 31 | from color import Coloring |
| 32 | import platform_utils | 32 | import platform_utils |
| 33 | 33 | ||
| 34 | |||
| 34 | class Status(PagedCommand): | 35 | class Status(PagedCommand): |
| 35 | common = True | 36 | common = True |
| 36 | helpSummary = "Show the working tree status" | 37 | helpSummary = "Show the working tree status" |
diff --git a/subcmds/sync.py b/subcmds/sync.py index 1ea102c0..c433ce6f 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -53,6 +53,7 @@ except ImportError: | |||
| 53 | 53 | ||
| 54 | try: | 54 | try: |
| 55 | import resource | 55 | import resource |
| 56 | |||
| 56 | def _rlimit_nofile(): | 57 | def _rlimit_nofile(): |
| 57 | return resource.getrlimit(resource.RLIMIT_NOFILE) | 58 | return resource.getrlimit(resource.RLIMIT_NOFILE) |
| 58 | except ImportError: | 59 | except ImportError: |
| @@ -81,13 +82,16 @@ from manifest_xml import GitcManifest | |||
| 81 | 82 | ||
| 82 | _ONE_DAY_S = 24 * 60 * 60 | 83 | _ONE_DAY_S = 24 * 60 * 60 |
| 83 | 84 | ||
| 85 | |||
| 84 | class _FetchError(Exception): | 86 | class _FetchError(Exception): |
| 85 | """Internal error thrown in _FetchHelper() when we don't want stack trace.""" | 87 | """Internal error thrown in _FetchHelper() when we don't want stack trace.""" |
| 86 | pass | 88 | pass |
| 87 | 89 | ||
| 90 | |||
| 88 | class _CheckoutError(Exception): | 91 | class _CheckoutError(Exception): |
| 89 | """Internal error thrown in _CheckoutOne() when we don't want stack trace.""" | 92 | """Internal error thrown in _CheckoutOne() when we don't want stack trace.""" |
| 90 | 93 | ||
| 94 | |||
| 91 | class Sync(Command, MirrorSafeCommand): | 95 | class Sync(Command, MirrorSafeCommand): |
| 92 | jobs = 1 | 96 | jobs = 1 |
| 93 | common = True | 97 | common = True |
| @@ -1044,6 +1048,7 @@ later is required to fix a server side protocol bug. | |||
| 1044 | file=sys.stderr) | 1048 | file=sys.stderr) |
| 1045 | sys.exit(1) | 1049 | sys.exit(1) |
| 1046 | 1050 | ||
| 1051 | |||
| 1047 | def _PostRepoUpgrade(manifest, quiet=False): | 1052 | def _PostRepoUpgrade(manifest, quiet=False): |
| 1048 | wrapper = Wrapper() | 1053 | wrapper = Wrapper() |
| 1049 | if wrapper.NeedSetupGnuPG(): | 1054 | if wrapper.NeedSetupGnuPG(): |
| @@ -1052,6 +1057,7 @@ def _PostRepoUpgrade(manifest, quiet=False): | |||
| 1052 | if project.Exists: | 1057 | if project.Exists: |
| 1053 | project.PostRepoUpgrade() | 1058 | project.PostRepoUpgrade() |
| 1054 | 1059 | ||
| 1060 | |||
| 1055 | def _PostRepoFetch(rp, no_repo_verify=False, verbose=False): | 1061 | def _PostRepoFetch(rp, no_repo_verify=False, verbose=False): |
| 1056 | if rp.HasChanges: | 1062 | if rp.HasChanges: |
| 1057 | print('info: A new version of repo is available', file=sys.stderr) | 1063 | print('info: A new version of repo is available', file=sys.stderr) |
| @@ -1070,6 +1076,7 @@ def _PostRepoFetch(rp, no_repo_verify=False, verbose=False): | |||
| 1070 | print('repo version %s is current' % rp.work_git.describe(HEAD), | 1076 | print('repo version %s is current' % rp.work_git.describe(HEAD), |
| 1071 | file=sys.stderr) | 1077 | file=sys.stderr) |
| 1072 | 1078 | ||
| 1079 | |||
| 1073 | def _VerifyTag(project): | 1080 | def _VerifyTag(project): |
| 1074 | gpg_dir = os.path.expanduser('~/.repoconfig/gnupg') | 1081 | gpg_dir = os.path.expanduser('~/.repoconfig/gnupg') |
| 1075 | if not os.path.exists(gpg_dir): | 1082 | if not os.path.exists(gpg_dir): |
| @@ -1174,6 +1181,8 @@ class _FetchTimes(object): | |||
| 1174 | # and supporting persistent-http[s]. It cannot change hosts from | 1181 | # and supporting persistent-http[s]. It cannot change hosts from |
| 1175 | # request to request like the normal transport, the real url | 1182 | # request to request like the normal transport, the real url |
| 1176 | # is passed during initialization. | 1183 | # is passed during initialization. |
| 1184 | |||
| 1185 | |||
| 1177 | class PersistentTransport(xmlrpc.client.Transport): | 1186 | class PersistentTransport(xmlrpc.client.Transport): |
| 1178 | def __init__(self, orig_host): | 1187 | def __init__(self, orig_host): |
| 1179 | self.orig_host = orig_host | 1188 | self.orig_host = orig_host |
diff --git a/subcmds/upload.py b/subcmds/upload.py index 180496fc..bc373b3e 100644 --- a/subcmds/upload.py +++ b/subcmds/upload.py | |||
| @@ -33,6 +33,7 @@ else: | |||
| 33 | 33 | ||
| 34 | UNUSUAL_COMMIT_THRESHOLD = 5 | 34 | UNUSUAL_COMMIT_THRESHOLD = 5 |
| 35 | 35 | ||
| 36 | |||
| 36 | def _ConfirmManyUploads(multiple_branches=False): | 37 | def _ConfirmManyUploads(multiple_branches=False): |
| 37 | if multiple_branches: | 38 | if multiple_branches: |
| 38 | print('ATTENTION: One or more branches has an unusually high number ' | 39 | print('ATTENTION: One or more branches has an unusually high number ' |
| @@ -44,17 +45,20 @@ def _ConfirmManyUploads(multiple_branches=False): | |||
| 44 | answer = input("If you are sure you intend to do this, type 'yes': ").strip() | 45 | answer = input("If you are sure you intend to do this, type 'yes': ").strip() |
| 45 | return answer == "yes" | 46 | return answer == "yes" |
| 46 | 47 | ||
| 48 | |||
| 47 | def _die(fmt, *args): | 49 | def _die(fmt, *args): |
| 48 | msg = fmt % args | 50 | msg = fmt % args |
| 49 | print('error: %s' % msg, file=sys.stderr) | 51 | print('error: %s' % msg, file=sys.stderr) |
| 50 | sys.exit(1) | 52 | sys.exit(1) |
| 51 | 53 | ||
| 54 | |||
| 52 | def _SplitEmails(values): | 55 | def _SplitEmails(values): |
| 53 | result = [] | 56 | result = [] |
| 54 | for value in values: | 57 | for value in values: |
| 55 | result.extend([s.strip() for s in value.split(',')]) | 58 | result.extend([s.strip() for s in value.split(',')]) |
| 56 | return result | 59 | return result |
| 57 | 60 | ||
| 61 | |||
| 58 | class Upload(InteractiveCommand): | 62 | class Upload(InteractiveCommand): |
| 59 | common = True | 63 | common = True |
| 60 | helpSummary = "Upload changes for code review" | 64 | helpSummary = "Upload changes for code review" |
diff --git a/subcmds/version.py b/subcmds/version.py index 761172b7..92316549 100644 --- a/subcmds/version.py +++ b/subcmds/version.py | |||
| @@ -20,6 +20,7 @@ from command import Command, MirrorSafeCommand | |||
| 20 | from git_command import git, RepoSourceVersion, user_agent | 20 | from git_command import git, RepoSourceVersion, user_agent |
| 21 | from git_refs import HEAD | 21 | from git_refs import HEAD |
| 22 | 22 | ||
| 23 | |||
| 23 | class Version(Command, MirrorSafeCommand): | 24 | class Version(Command, MirrorSafeCommand): |
| 24 | wrapper_version = None | 25 | wrapper_version = None |
| 25 | wrapper_path = None | 26 | wrapper_path = None |
diff --git a/tests/test_git_config.py b/tests/test_git_config.py index b735f27f..6aa6b381 100644 --- a/tests/test_git_config.py +++ b/tests/test_git_config.py | |||
| @@ -23,14 +23,17 @@ import unittest | |||
| 23 | 23 | ||
| 24 | import git_config | 24 | import git_config |
| 25 | 25 | ||
| 26 | |||
| 26 | def fixture(*paths): | 27 | def fixture(*paths): |
| 27 | """Return a path relative to test/fixtures. | 28 | """Return a path relative to test/fixtures. |
| 28 | """ | 29 | """ |
| 29 | return os.path.join(os.path.dirname(__file__), 'fixtures', *paths) | 30 | return os.path.join(os.path.dirname(__file__), 'fixtures', *paths) |
| 30 | 31 | ||
| 32 | |||
| 31 | class GitConfigUnitTest(unittest.TestCase): | 33 | class GitConfigUnitTest(unittest.TestCase): |
| 32 | """Tests the GitConfig class. | 34 | """Tests the GitConfig class. |
| 33 | """ | 35 | """ |
| 36 | |||
| 34 | def setUp(self): | 37 | def setUp(self): |
| 35 | """Create a GitConfig object using the test.gitconfig fixture. | 38 | """Create a GitConfig object using the test.gitconfig fixture. |
| 36 | """ | 39 | """ |
| @@ -68,5 +71,6 @@ class GitConfigUnitTest(unittest.TestCase): | |||
| 68 | val = config.GetString('empty') | 71 | val = config.GetString('empty') |
| 69 | self.assertEqual(val, None) | 72 | self.assertEqual(val, None) |
| 70 | 73 | ||
| 74 | |||
| 71 | if __name__ == '__main__': | 75 | if __name__ == '__main__': |
| 72 | unittest.main() | 76 | unittest.main() |
diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 8ef8d48d..38def512 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py | |||
| @@ -23,14 +23,17 @@ import unittest | |||
| 23 | 23 | ||
| 24 | import wrapper | 24 | import wrapper |
| 25 | 25 | ||
| 26 | |||
| 26 | def fixture(*paths): | 27 | def fixture(*paths): |
| 27 | """Return a path relative to tests/fixtures. | 28 | """Return a path relative to tests/fixtures. |
| 28 | """ | 29 | """ |
| 29 | return os.path.join(os.path.dirname(__file__), 'fixtures', *paths) | 30 | return os.path.join(os.path.dirname(__file__), 'fixtures', *paths) |
| 30 | 31 | ||
| 32 | |||
| 31 | class RepoWrapperUnitTest(unittest.TestCase): | 33 | class RepoWrapperUnitTest(unittest.TestCase): |
| 32 | """Tests helper functions in the repo wrapper | 34 | """Tests helper functions in the repo wrapper |
| 33 | """ | 35 | """ |
| 36 | |||
| 34 | def setUp(self): | 37 | def setUp(self): |
| 35 | """Load the wrapper module every time | 38 | """Load the wrapper module every time |
| 36 | """ | 39 | """ |
| @@ -76,5 +79,6 @@ class RepoWrapperUnitTest(unittest.TestCase): | |||
| 76 | self.assertEqual(self.wrapper.gitc_parse_clientdir('/gitc/manifest-rw/'), None) | 79 | self.assertEqual(self.wrapper.gitc_parse_clientdir('/gitc/manifest-rw/'), None) |
| 77 | self.assertEqual(self.wrapper.gitc_parse_clientdir('/test/usr/local/google/gitc/'), None) | 80 | self.assertEqual(self.wrapper.gitc_parse_clientdir('/test/usr/local/google/gitc/'), None) |
| 78 | 81 | ||
| 82 | |||
| 79 | if __name__ == '__main__': | 83 | if __name__ == '__main__': |
| 80 | unittest.main() | 84 | unittest.main() |
| @@ -27,7 +27,10 @@ import os | |||
| 27 | def WrapperPath(): | 27 | def WrapperPath(): |
| 28 | return os.path.join(os.path.dirname(__file__), 'repo') | 28 | return os.path.join(os.path.dirname(__file__), 'repo') |
| 29 | 29 | ||
| 30 | |||
| 30 | _wrapper_module = None | 31 | _wrapper_module = None |
| 32 | |||
| 33 | |||
| 31 | def Wrapper(): | 34 | def Wrapper(): |
| 32 | global _wrapper_module | 35 | global _wrapper_module |
| 33 | if not _wrapper_module: | 36 | if not _wrapper_module: |
