OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
7 | 7 |
8 """A git-command for integrating reviews on Rietveld and Gerrit.""" | 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" |
9 | 9 |
10 from distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
11 from multiprocessing.pool import ThreadPool | 11 from multiprocessing.pool import ThreadPool |
12 import base64 | 12 import base64 |
13 import collections | 13 import collections |
14 import glob | 14 import glob |
15 import httplib | 15 import httplib |
16 import json | 16 import json |
17 import logging | 17 import logging |
| 18 import multiprocessing |
18 import optparse | 19 import optparse |
19 import os | 20 import os |
20 import Queue | 21 import Queue |
21 import re | 22 import re |
22 import stat | 23 import stat |
23 import sys | 24 import sys |
24 import tempfile | 25 import tempfile |
25 import textwrap | 26 import textwrap |
26 import time | 27 import time |
27 import traceback | 28 import traceback |
(...skipping 2889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2917 status = cl.GetStatus() | 2918 status = cl.GetStatus() |
2918 | 2919 |
2919 if url and (not status or status == 'error'): | 2920 if url and (not status or status == 'error'): |
2920 # The issue probably doesn't exist anymore. | 2921 # The issue probably doesn't exist anymore. |
2921 url += ' (broken)' | 2922 url += ' (broken)' |
2922 | 2923 |
2923 return (branch, url, status) | 2924 return (branch, url, status) |
2924 | 2925 |
2925 def get_cl_statuses( | 2926 def get_cl_statuses( |
2926 branches, fine_grained, max_processes=None, auth_config=None): | 2927 branches, fine_grained, max_processes=None, auth_config=None): |
2927 """Returns a blocking iterable of (branch, issue, color) for given branches. | 2928 """Returns a blocking iterable of (branch, issue, status) for given branches. |
2928 | 2929 |
2929 If fine_grained is true, this will fetch CL statuses from the server. | 2930 If fine_grained is true, this will fetch CL statuses from the server. |
2930 Otherwise, simply indicate if there's a matching url for the given branches. | 2931 Otherwise, simply indicate if there's a matching url for the given branches. |
2931 | 2932 |
2932 If max_processes is specified, it is used as the maximum number of processes | 2933 If max_processes is specified, it is used as the maximum number of processes |
2933 to spawn to fetch CL status from the server. Otherwise 1 process per branch is | 2934 to spawn to fetch CL status from the server. Otherwise 1 process per branch is |
2934 spawned. | 2935 spawned. |
| 2936 |
| 2937 See GetStatus() for a list of possible statuses. |
2935 """ | 2938 """ |
| 2939 def fetch(branch): |
| 2940 if not branch: |
| 2941 return None |
| 2942 |
| 2943 return fetch_cl_status(branch, auth_config=auth_config) |
| 2944 |
2936 # Silence upload.py otherwise it becomes unwieldly. | 2945 # Silence upload.py otherwise it becomes unwieldly. |
2937 upload.verbosity = 0 | 2946 upload.verbosity = 0 |
2938 | 2947 |
2939 if fine_grained: | 2948 if fine_grained: |
2940 # Process one branch synchronously to work through authentication, then | 2949 # Process one branch synchronously to work through authentication, then |
2941 # spawn processes to process all the other branches in parallel. | 2950 # spawn processes to process all the other branches in parallel. |
2942 if branches: | 2951 if branches: |
2943 fetch = lambda branch: fetch_cl_status(branch, auth_config=auth_config) | 2952 |
2944 yield fetch(branches[0]) | 2953 yield fetch(branches[0]) |
2945 | 2954 |
2946 branches_to_fetch = branches[1:] | 2955 branches_to_fetch = branches[1:] |
2947 pool = ThreadPool( | 2956 pool = ThreadPool( |
2948 min(max_processes, len(branches_to_fetch)) | 2957 min(max_processes, len(branches_to_fetch)) |
2949 if max_processes is not None | 2958 if max_processes is not None |
2950 else len(branches_to_fetch)) | 2959 else len(branches_to_fetch)) |
2951 for x in pool.imap_unordered(fetch, branches_to_fetch): | 2960 |
2952 yield x | 2961 fetched_branches = set() |
| 2962 it = pool.imap_unordered(fetch, branches_to_fetch).__iter__() |
| 2963 while True: |
| 2964 try: |
| 2965 row = it.next(timeout=5) |
| 2966 except multiprocessing.TimeoutError: |
| 2967 break |
| 2968 |
| 2969 fetched_branches.add(row[0]) |
| 2970 yield row |
| 2971 |
| 2972 # Add any branches that failed to fetch. |
| 2973 for b in set(branches_to_fetch) - fetched_branches: |
| 2974 cl = Changelist(branchref=b, auth_config=auth_config) |
| 2975 yield (b, cl.GetIssueURL() if b else None, 'error') |
| 2976 |
2953 else: | 2977 else: |
2954 # Do not use GetApprovingReviewers(), since it requires an HTTP request. | 2978 # Do not use GetApprovingReviewers(), since it requires an HTTP request. |
2955 for b in branches: | 2979 for b in branches: |
2956 cl = Changelist(branchref=b, auth_config=auth_config) | 2980 cl = Changelist(branchref=b, auth_config=auth_config) |
2957 url = cl.GetIssueURL() | 2981 url = cl.GetIssueURL() if b else None |
2958 yield (b, url, 'waiting' if url else 'error') | 2982 yield (b, url, 'waiting' if url else 'error') |
2959 | 2983 |
2960 | 2984 |
2961 def upload_branch_deps(cl, args): | 2985 def upload_branch_deps(cl, args): |
2962 """Uploads CLs of local branches that are dependents of the current branch. | 2986 """Uploads CLs of local branches that are dependents of the current branch. |
2963 | 2987 |
2964 If the local branch dependency tree looks like: | 2988 If the local branch dependency tree looks like: |
2965 test1 -> test2.1 -> test3.1 | 2989 test1 -> test2.1 -> test3.1 |
2966 -> test3.2 | 2990 -> test3.2 |
2967 -> test2.2 -> test3.3 | 2991 -> test2.2 -> test3.3 |
(...skipping 1887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4855 if __name__ == '__main__': | 4879 if __name__ == '__main__': |
4856 # These affect sys.stdout so do it outside of main() to simplify mocks in | 4880 # These affect sys.stdout so do it outside of main() to simplify mocks in |
4857 # unit testing. | 4881 # unit testing. |
4858 fix_encoding.fix_encoding() | 4882 fix_encoding.fix_encoding() |
4859 setup_color.init() | 4883 setup_color.init() |
4860 try: | 4884 try: |
4861 sys.exit(main(sys.argv[1:])) | 4885 sys.exit(main(sys.argv[1:])) |
4862 except KeyboardInterrupt: | 4886 except KeyboardInterrupt: |
4863 sys.stderr.write('interrupted\n') | 4887 sys.stderr.write('interrupted\n') |
4864 sys.exit(1) | 4888 sys.exit(1) |
OLD | NEW |