Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: git_cl.py

Issue 519563002: Make git-cl-land wait (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.""" 8 """A git-command for integrating reviews on Rietveld."""
9 9
10 from distutils.version import LooseVersion 10 from distutils.version import LooseVersion
(...skipping 1875 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 base_svn_head += '^1' 1886 base_svn_head += '^1'
1887 1887
1888 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head]) 1888 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head])
1889 if extra_commits: 1889 if extra_commits:
1890 print ('This branch has %d additional commits not upstreamed yet.' 1890 print ('This branch has %d additional commits not upstreamed yet.'
1891 % len(extra_commits.splitlines())) 1891 % len(extra_commits.splitlines()))
1892 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' 1892 print ('Upstream "%s" or rebase this branch on top of the upstream trunk '
1893 'before attempting to %s.' % (base_branch, cmd)) 1893 'before attempting to %s.' % (base_branch, cmd))
1894 return 1 1894 return 1
1895 1895
1896 base_branch = RunGit(['merge-base', base_branch, 'HEAD']).strip() 1896 merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip()
1897 if not options.bypass_hooks: 1897 if not options.bypass_hooks:
1898 author = None 1898 author = None
1899 if options.contributor: 1899 if options.contributor:
1900 author = re.search(r'\<(.*)\>', options.contributor).group(1) 1900 author = re.search(r'\<(.*)\>', options.contributor).group(1)
1901 hook_results = cl.RunHook( 1901 hook_results = cl.RunHook(
1902 committing=True, 1902 committing=True,
1903 may_prompt=not options.force, 1903 may_prompt=not options.force,
1904 verbose=options.verbose, 1904 verbose=options.verbose,
1905 change=cl.GetChange(base_branch, author)) 1905 change=cl.GetChange(merge_base, author))
1906 if not hook_results.should_continue(): 1906 if not hook_results.should_continue():
1907 return 1 1907 return 1
1908 1908
1909 # Check the tree status if the tree status URL is set. 1909 # Check the tree status if the tree status URL is set.
1910 status = GetTreeStatus() 1910 status = GetTreeStatus()
1911 if 'closed' == status: 1911 if 'closed' == status:
1912 print('The tree is closed. Please wait for it to reopen. Use ' 1912 print('The tree is closed. Please wait for it to reopen. Use '
1913 '"git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) 1913 '"git cl %s --bypass-hooks" to commit on a closed tree.' % cmd)
1914 return 1 1914 return 1
1915 elif 'unknown' == status: 1915 elif 'unknown' == status:
1916 print('Unable to determine tree status. Please verify manually and ' 1916 print('Unable to determine tree status. Please verify manually and '
1917 'use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) 1917 'use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd)
1918 return 1 1918 return 1
1919 else: 1919 else:
1920 breakpad.SendStack( 1920 breakpad.SendStack(
1921 'GitClHooksBypassedCommit', 1921 'GitClHooksBypassedCommit',
1922 'Issue %s/%s bypassed hook when committing (tree status was "%s")' % 1922 'Issue %s/%s bypassed hook when committing (tree status was "%s")' %
1923 (cl.GetRietveldServer(), cl.GetIssue(), GetTreeStatus()), 1923 (cl.GetRietveldServer(), cl.GetIssue(), GetTreeStatus()),
1924 verbose=False) 1924 verbose=False)
1925 1925
1926 change_desc = ChangeDescription(options.message) 1926 change_desc = ChangeDescription(options.message)
1927 if not change_desc.description and cl.GetIssue(): 1927 if not change_desc.description and cl.GetIssue():
1928 change_desc = ChangeDescription(cl.GetDescription()) 1928 change_desc = ChangeDescription(cl.GetDescription())
1929 1929
1930 if not change_desc.description: 1930 if not change_desc.description:
1931 if not cl.GetIssue() and options.bypass_hooks: 1931 if not cl.GetIssue() and options.bypass_hooks:
1932 change_desc = ChangeDescription(CreateDescriptionFromLog([base_branch])) 1932 change_desc = ChangeDescription(CreateDescriptionFromLog([merge_base]))
1933 else: 1933 else:
1934 print 'No description set.' 1934 print 'No description set.'
1935 print 'Visit %s/edit to set it.' % (cl.GetIssueURL()) 1935 print 'Visit %s/edit to set it.' % (cl.GetIssueURL())
1936 return 1 1936 return 1
1937 1937
1938 # Keep a separate copy for the commit message, because the commit message 1938 # Keep a separate copy for the commit message, because the commit message
1939 # contains the link to the Rietveld issue, while the Rietveld message contains 1939 # contains the link to the Rietveld issue, while the Rietveld message contains
1940 # the commit viewvc url. 1940 # the commit viewvc url.
1941 # Keep a separate copy for the commit message. 1941 # Keep a separate copy for the commit message.
1942 if cl.GetIssue(): 1942 if cl.GetIssue():
1943 change_desc.update_reviewers(cl.GetApprovingReviewers()) 1943 change_desc.update_reviewers(cl.GetApprovingReviewers())
1944 1944
1945 commit_desc = ChangeDescription(change_desc.description) 1945 commit_desc = ChangeDescription(change_desc.description)
1946 if cl.GetIssue(): 1946 if cl.GetIssue():
1947 commit_desc.append_footer('Review URL: %s' % cl.GetIssueURL()) 1947 commit_desc.append_footer('Review URL: %s' % cl.GetIssueURL())
1948 if options.contributor: 1948 if options.contributor:
1949 commit_desc.append_footer('Patch from %s.' % options.contributor) 1949 commit_desc.append_footer('Patch from %s.' % options.contributor)
1950 1950
1951 print('Description:') 1951 print('Description:')
1952 print(commit_desc.description) 1952 print(commit_desc.description)
1953 1953
1954 branches = [base_branch, cl.GetBranchRef()] 1954 branches = [merge_base, cl.GetBranchRef()]
1955 if not options.force: 1955 if not options.force:
1956 print_stats(options.similarity, options.find_copies, branches) 1956 print_stats(options.similarity, options.find_copies, branches)
1957 1957
1958 # We want to squash all this branch's commits into one commit with the proper 1958 # We want to squash all this branch's commits into one commit with the proper
1959 # description. We do this by doing a "reset --soft" to the base branch (which 1959 # description. We do this by doing a "reset --soft" to the base branch (which
1960 # keeps the working copy the same), then dcommitting that. If origin/master 1960 # keeps the working copy the same), then dcommitting that. If origin/master
1961 # has a submodule merge commit, we'll also need to cherry-pick the squashed 1961 # has a submodule merge commit, we'll also need to cherry-pick the squashed
1962 # commit onto a branch based on the git-svn head. 1962 # commit onto a branch based on the git-svn head.
1963 MERGE_BRANCH = 'git-cl-commit' 1963 MERGE_BRANCH = 'git-cl-commit'
1964 CHERRY_PICK_BRANCH = 'git-cl-cherry-pick' 1964 CHERRY_PICK_BRANCH = 'git-cl-cherry-pick'
1965 # Delete the branches if they exist. 1965 # Delete the branches if they exist.
1966 for branch in [MERGE_BRANCH, CHERRY_PICK_BRANCH]: 1966 for branch in [MERGE_BRANCH, CHERRY_PICK_BRANCH]:
1967 showref_cmd = ['show-ref', '--quiet', '--verify', 'refs/heads/%s' % branch] 1967 showref_cmd = ['show-ref', '--quiet', '--verify', 'refs/heads/%s' % branch]
1968 result = RunGitWithCode(showref_cmd) 1968 result = RunGitWithCode(showref_cmd)
1969 if result[0] == 0: 1969 if result[0] == 0:
1970 RunGit(['branch', '-D', branch]) 1970 RunGit(['branch', '-D', branch])
1971 1971
1972 # We might be in a directory that's present in this branch but not in the 1972 # We might be in a directory that's present in this branch but not in the
1973 # trunk. Move up to the top of the tree so that git commands that expect a 1973 # trunk. Move up to the top of the tree so that git commands that expect a
1974 # valid CWD won't fail after we check out the merge branch. 1974 # valid CWD won't fail after we check out the merge branch.
1975 rel_base_path = settings.GetRelativeRoot() 1975 rel_base_path = settings.GetRelativeRoot()
1976 if rel_base_path: 1976 if rel_base_path:
1977 os.chdir(rel_base_path) 1977 os.chdir(rel_base_path)
1978 1978
1979 # Stuff our change into the merge branch. 1979 # Stuff our change into the merge branch.
1980 # We wrap in a try...finally block so if anything goes wrong, 1980 # We wrap in a try...finally block so if anything goes wrong,
1981 # we clean up the branches. 1981 # we clean up the branches.
1982 retcode = -1 1982 retcode = -1
1983 used_pending = False 1983 pushed_to_pending = False
1984 pending_ref = None 1984 pending_ref = None
1985 try: 1985 try:
1986 RunGit(['checkout', '-q', '-b', MERGE_BRANCH]) 1986 RunGit(['checkout', '-q', '-b', MERGE_BRANCH])
1987 RunGit(['reset', '--soft', base_branch]) 1987 RunGit(['reset', '--soft', merge_base])
1988 if options.contributor: 1988 if options.contributor:
1989 RunGit( 1989 RunGit(
1990 [ 1990 [
1991 'commit', '--author', options.contributor, 1991 'commit', '--author', options.contributor,
1992 '-m', commit_desc.description, 1992 '-m', commit_desc.description,
1993 ]) 1993 ])
1994 else: 1994 else:
1995 RunGit(['commit', '-m', commit_desc.description]) 1995 RunGit(['commit', '-m', commit_desc.description])
1996 if base_has_submodules: 1996 if base_has_submodules:
1997 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() 1997 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip()
1998 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) 1998 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head])
1999 RunGit(['checkout', CHERRY_PICK_BRANCH]) 1999 RunGit(['checkout', CHERRY_PICK_BRANCH])
2000 RunGit(['cherry-pick', cherry_pick_commit]) 2000 RunGit(['cherry-pick', cherry_pick_commit])
2001 if cmd == 'land': 2001 if cmd == 'land':
2002 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) 2002 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch())
2003 pending_prefix = settings.GetPendingRefPrefix() 2003 pending_prefix = settings.GetPendingRefPrefix()
2004 if not pending_prefix or branch.startswith(pending_prefix): 2004 if not pending_prefix or branch.startswith(pending_prefix):
2005 # If not using refs/pending/heads/* at all, or target ref is already set 2005 # If not using refs/pending/heads/* at all, or target ref is already set
2006 # to pending, then push to the target ref directly. 2006 # to pending, then push to the target ref directly.
2007 retcode, output = RunGitWithCode( 2007 retcode, output = RunGitWithCode(
2008 ['push', '--porcelain', remote, 'HEAD:%s' % branch]) 2008 ['push', '--porcelain', remote, 'HEAD:%s' % branch])
2009 used_pending = pending_prefix and branch.startswith(pending_prefix) 2009 pushed_to_pending = pending_prefix and branch.startswith(pending_prefix)
2010 else: 2010 else:
2011 # Cherry-pick the change on top of pending ref and then push it. 2011 # Cherry-pick the change on top of pending ref and then push it.
2012 assert branch.startswith('refs/'), branch 2012 assert branch.startswith('refs/'), branch
2013 assert pending_prefix[-1] == '/', pending_prefix 2013 assert pending_prefix[-1] == '/', pending_prefix
2014 pending_ref = pending_prefix + branch[len('refs/'):] 2014 pending_ref = pending_prefix + branch[len('refs/'):]
2015 retcode, output = PushToGitPending(remote, pending_ref, branch) 2015 retcode, output = PushToGitPending(remote, pending_ref, branch)
2016 used_pending = (retcode == 0) 2016 pushed_to_pending = (retcode == 0)
2017 logging.debug(output) 2017 logging.debug(output)
2018 else: 2018 else:
2019 # dcommit the merge branch. 2019 # dcommit the merge branch.
2020 retcode, output = RunGitWithCode(['svn', 'dcommit', 2020 retcode, output = RunGitWithCode(['svn', 'dcommit',
2021 '-C%s' % options.similarity, 2021 '-C%s' % options.similarity,
2022 '--no-rebase', '--rmdir']) 2022 '--no-rebase', '--rmdir'])
2023 finally: 2023 finally:
2024 # And then swap back to the original branch and clean up. 2024 # And then swap back to the original branch and clean up.
2025 RunGit(['checkout', '-q', cl.GetBranch()]) 2025 RunGit(['checkout', '-q', cl.GetBranch()])
2026 RunGit(['branch', '-D', MERGE_BRANCH]) 2026 RunGit(['branch', '-D', MERGE_BRANCH])
2027 if base_has_submodules: 2027 if base_has_submodules:
2028 RunGit(['branch', '-D', CHERRY_PICK_BRANCH]) 2028 RunGit(['branch', '-D', CHERRY_PICK_BRANCH])
2029 2029
2030 revision = None
2031 if retcode == 0 and pushed_to_pending:
2032 try:
2033 revision = WaitForRealCommit(remote, base_branch, branch)[:7]
2034 # We set pushed_to_pending to False, since it made it all the way to the
2035 # real ref.
2036 pushed_to_pending = False
2037 except KeyboardInterrupt:
2038 pass
2039
2030 if cl.GetIssue(): 2040 if cl.GetIssue():
2031 if cmd == 'dcommit' and 'Committed r' in output: 2041 if not revision:
2032 revision = re.match('.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1) 2042 if cmd == 'dcommit' and 'Committed r' in output:
2033 elif cmd == 'land' and retcode == 0: 2043 revision = re.match(
2034 match = (re.match(r'.*?([a-f0-9]{7,})\.\.([a-f0-9]{7,})$', l) 2044 '.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1)
2035 for l in output.splitlines(False)) 2045 elif cmd == 'land' and retcode == 0:
2036 match = filter(None, match) 2046 match = (re.match(r'.*?([a-f0-9]{7,})\.\.([a-f0-9]{7,})$', l)
2037 if len(match) != 1: 2047 for l in output.splitlines(False))
2038 DieWithError("Couldn't parse ouput to extract the committed hash:\n%s" % 2048 match = filter(None, match)
2039 output) 2049 if len(match) != 1:
2040 revision = match[0].group(2) 2050 DieWithError(
2041 else: 2051 "Couldn't parse ouput to extract the committed hash:\n%s" % output)
2042 return 1 2052 revision = match[0].group(2)
2043 to_pending = ' to pending queue' if used_pending else '' 2053 else:
2054 return 1
2055
2056 to_pending = ' to pending queue' if pushed_to_pending else ''
2044 viewvc_url = settings.GetViewVCUrl() 2057 viewvc_url = settings.GetViewVCUrl()
2045 if viewvc_url and revision: 2058 if not to_pending:
2046 change_desc.append_footer( 2059 if viewvc_url and revision:
2047 'Committed%s: %s%s' % (to_pending, viewvc_url, revision)) 2060 change_desc.append_footer(
2048 elif revision: 2061 'Committed: %s%s' % (viewvc_url, revision))
2049 change_desc.append_footer('Committed%s: %s' % (to_pending, revision)) 2062 elif revision:
2063 change_desc.append_footer('Committed: %s' % (revision,))
2050 print ('Closing issue ' 2064 print ('Closing issue '
2051 '(you may be prompted for your codereview password)...') 2065 '(you may be prompted for your codereview password)...')
2052 cl.UpdateDescription(change_desc.description) 2066 cl.UpdateDescription(change_desc.description)
2053 cl.CloseIssue() 2067 cl.CloseIssue()
2054 props = cl.GetIssueProperties() 2068 props = cl.GetIssueProperties()
2055 patch_num = len(props['patchsets']) 2069 patch_num = len(props['patchsets'])
2056 comment = "Committed patchset #%d (id:%d)%s manually as %s" % ( 2070 comment = "Committed patchset #%d (id:%d)%s manually as %s" % (
2057 patch_num, props['patchsets'][-1], to_pending, revision) 2071 patch_num, props['patchsets'][-1], to_pending, revision)
2058 if options.bypass_hooks: 2072 if options.bypass_hooks:
2059 comment += ' (tree was closed).' if GetTreeStatus() == 'closed' else '.' 2073 comment += ' (tree was closed).' if GetTreeStatus() == 'closed' else '.'
2060 else: 2074 else:
2061 comment += ' (presubmit successful).' 2075 comment += ' (presubmit successful).'
2062 cl.RpcServer().add_comment(cl.GetIssue(), comment) 2076 cl.RpcServer().add_comment(cl.GetIssue(), comment)
2063 cl.SetIssue(None) 2077 cl.SetIssue(None)
2064 2078
2065 if used_pending and retcode == 0: 2079 if pushed_to_pending and retcode == 0:
2066 _, branch = cl.FetchUpstreamTuple(cl.GetBranch()) 2080 _, branch = cl.FetchUpstreamTuple(cl.GetBranch())
2067 print 'The commit is in the pending queue (%s).' % pending_ref 2081 print 'The commit is in the pending queue (%s).' % pending_ref
2068 print ( 2082 print (
2069 'It will show up on %s in ~1 min, once it gets Cr-Commit-Position ' 2083 'It will show up on %s in ~1 min, once it gets Cr-Commit-Position '
2070 'footer.' % branch) 2084 'footer.' % branch)
2071 2085
2072 if retcode == 0: 2086 if retcode == 0:
2073 hook = POSTUPSTREAM_HOOK_PATTERN % cmd 2087 hook = POSTUPSTREAM_HOOK_PATTERN % cmd
2074 if os.path.isfile(hook): 2088 if os.path.isfile(hook):
2075 RunCommand([hook, base_branch], error_ok=True) 2089 RunCommand([hook, merge_base], error_ok=True)
2076 2090
2077 return 0 2091 return 0
2078 2092
2079 2093
2094 def WaitForRealCommit(remote, local_base_ref, real_ref):
2095 print
2096 print 'Waiting for commit to be landed on %s...' % real_ref
2097 print '(If you are impatient, you may Ctrl-C once without harm)'
2098 target_tree = RunGit(['rev-parse', 'HEAD:']).strip()
Vadim Sh. 2014/08/29 01:09:37 Is HEAD really what you want here? HEAD is cl.GetB
iannucci 2014/08/29 01:24:24 Fixed in PS2
2099 current_rev = RunGit(['rev-parse', local_base_ref]).strip()
Vadim Sh. 2014/08/29 01:09:37 It's latest local revision fetched from remote?
iannucci 2014/08/29 01:24:24 yeah
2100
2101 loop = 0
2102 while True:
2103 sys.stdout.write('fetching (%d)... \r' % loop)
2104 sys.stdout.flush()
2105 loop += 1
2106
2107 RunGit(['retry', 'fetch', remote, real_ref], stderr=subprocess2.VOID)
Vadim Sh. 2014/08/29 01:09:37 let's remove stderr supression, people want to kno
iannucci 2014/08/29 01:24:24 the fetching line above is enough. This just spams
2108 to_rev = RunGit(['rev-parse', 'FETCH_HEAD']).strip()
Vadim Sh. 2014/08/29 01:09:37 print this rev? so that people see that it's crawl
iannucci 2014/08/29 01:24:24 nah, it's too fast. spends all its time fetching
2109 commits = RunGit(['rev-list', '%s..%s' % (current_rev, to_rev)])
2110 for commit in commits.splitlines():
2111 if RunGit(['rev-parse', '%s:' % commit]).strip() == target_tree:
2112 print 'Found commit on %s' % real_ref
2113 return commit
2114
2115 current_rev = to_rev
2116
2117
2080 def PushToGitPending(remote, pending_ref, upstream_ref): 2118 def PushToGitPending(remote, pending_ref, upstream_ref):
2081 """Fetches pending_ref, cherry-picks current HEAD on top of it, pushes. 2119 """Fetches pending_ref, cherry-picks current HEAD on top of it, pushes.
2082 2120
2083 Returns: 2121 Returns:
2084 (retcode of last operation, output log of last operation). 2122 (retcode of last operation, output log of last operation).
2085 """ 2123 """
2086 assert pending_ref.startswith('refs/'), pending_ref 2124 assert pending_ref.startswith('refs/'), pending_ref
2087 local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):] 2125 local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):]
2088 cherry = RunGit(['rev-parse', 'HEAD']).strip() 2126 cherry = RunGit(['rev-parse', 'HEAD']).strip()
2089 code = 0 2127 code = 0
(...skipping 27 matching lines...) Expand all
2117 print 'Please rebase your patch and try again.' 2155 print 'Please rebase your patch and try again.'
2118 RunGitWithCode(['cherry-pick', '--abort']) 2156 RunGitWithCode(['cherry-pick', '--abort'])
2119 return code, out 2157 return code, out
2120 2158
2121 # Applied cleanly, try to push now. Retry on error (flake or non-ff push). 2159 # Applied cleanly, try to push now. Retry on error (flake or non-ff push).
2122 print 'Pushing commit to %s... It can take a while.' % pending_ref 2160 print 'Pushing commit to %s... It can take a while.' % pending_ref
2123 code, out = RunGitWithCode( 2161 code, out = RunGitWithCode(
2124 ['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref]) 2162 ['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref])
2125 if code == 0: 2163 if code == 0:
2126 # Success. 2164 # Success.
2165 print 'Commit pushed to pending ref successfully!'
2127 return code, out 2166 return code, out
2128 2167
2129 print 'Push failed with exit code %d.' % code 2168 print 'Push failed with exit code %d.' % code
2130 if out.strip(): 2169 if out.strip():
2131 print out.strip() 2170 print out.strip()
2132 if IsFatalPushFailure(out): 2171 if IsFatalPushFailure(out):
2133 print ( 2172 print (
2134 'Fatal push error. Make sure your .netrc credentials and git ' 2173 'Fatal push error. Make sure your .netrc credentials and git '
2135 'user.email are correct and you have push access to the repo.') 2174 'user.email are correct and you have push access to the repo.')
2136 return code, out 2175 return code, out
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
2765 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' 2804 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith '
2766 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) 2805 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)))
2767 2806
2768 2807
2769 if __name__ == '__main__': 2808 if __name__ == '__main__':
2770 # These affect sys.stdout so do it outside of main() to simplify mocks in 2809 # These affect sys.stdout so do it outside of main() to simplify mocks in
2771 # unit testing. 2810 # unit testing.
2772 fix_encoding.fix_encoding() 2811 fix_encoding.fix_encoding()
2773 colorama.init() 2812 colorama.init()
2774 sys.exit(main(sys.argv[1:])) 2813 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698