| 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.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
| 9 | 9 |
| 10 from distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
| (...skipping 1843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 help="don't commit after patch applies") | 1854 help="don't commit after patch applies") |
| 1855 (options, args) = parser.parse_args(args) | 1855 (options, args) = parser.parse_args(args) |
| 1856 if len(args) != 1: | 1856 if len(args) != 1: |
| 1857 parser.print_help() | 1857 parser.print_help() |
| 1858 return 1 | 1858 return 1 |
| 1859 issue_arg = args[0] | 1859 issue_arg = args[0] |
| 1860 | 1860 |
| 1861 # TODO(maruel): Use apply_issue.py | 1861 # TODO(maruel): Use apply_issue.py |
| 1862 # TODO(ukai): use gerrit-cherry-pick for gerrit repository? | 1862 # TODO(ukai): use gerrit-cherry-pick for gerrit repository? |
| 1863 | 1863 |
| 1864 if issue_arg.isdigit(): | 1864 if options.newbranch: |
| 1865 if options.force: |
| 1866 RunGit(['branch', '-D', options.newbranch], |
| 1867 stderr=subprocess2.PIPE, error_ok=True) |
| 1868 RunGit(['checkout', '-b', options.newbranch, |
| 1869 Changelist().GetUpstreamBranch()]) |
| 1870 |
| 1871 return PatchIssue(issue_arg, options.reject, options.nocommit) |
| 1872 |
| 1873 |
| 1874 def PatchIssue(issue_arg, reject, nocommit): |
| 1875 if type(issue_arg) is int or issue_arg.isdigit(): |
| 1865 # Input is an issue id. Figure out the URL. | 1876 # Input is an issue id. Figure out the URL. |
| 1866 issue = int(issue_arg) | 1877 issue = int(issue_arg) |
| 1867 cl = Changelist(issue=issue) | 1878 cl = Changelist(issue=issue) |
| 1868 patchset = cl.GetMostRecentPatchset() | 1879 patchset = cl.GetMostRecentPatchset() |
| 1869 patch_data = cl.GetPatchSetDiff(issue, patchset) | 1880 patch_data = cl.GetPatchSetDiff(issue, patchset) |
| 1870 else: | 1881 else: |
| 1871 # Assume it's a URL to the patch. Default to https. | 1882 # Assume it's a URL to the patch. Default to https. |
| 1872 issue_url = gclient_utils.UpgradeToHttps(issue_arg) | 1883 issue_url = gclient_utils.UpgradeToHttps(issue_arg) |
| 1873 match = re.match(r'.*?/issue(\d+)_(\d+).diff', issue_url) | 1884 match = re.match(r'.*?/issue(\d+)_(\d+).diff', issue_url) |
| 1874 if not match: | 1885 if not match: |
| 1875 DieWithError('Must pass an issue ID or full URL for ' | 1886 DieWithError('Must pass an issue ID or full URL for ' |
| 1876 '\'Download raw patch set\'') | 1887 '\'Download raw patch set\'') |
| 1877 issue = int(match.group(1)) | 1888 issue = int(match.group(1)) |
| 1878 patchset = int(match.group(2)) | 1889 patchset = int(match.group(2)) |
| 1879 patch_data = urllib2.urlopen(issue_arg).read() | 1890 patch_data = urllib2.urlopen(issue_arg).read() |
| 1880 | 1891 |
| 1881 if options.newbranch: | |
| 1882 if options.force: | |
| 1883 RunGit(['branch', '-D', options.newbranch], | |
| 1884 stderr=subprocess2.PIPE, error_ok=True) | |
| 1885 RunGit(['checkout', '-b', options.newbranch, | |
| 1886 Changelist().GetUpstreamBranch()]) | |
| 1887 | |
| 1888 # Switch up to the top-level directory, if necessary, in preparation for | 1892 # Switch up to the top-level directory, if necessary, in preparation for |
| 1889 # applying the patch. | 1893 # applying the patch. |
| 1890 top = RunGit(['rev-parse', '--show-cdup']).strip() | 1894 top = RunGit(['rev-parse', '--show-cdup']).strip() |
| 1891 if top: | 1895 if top: |
| 1892 os.chdir(top) | 1896 os.chdir(top) |
| 1893 | 1897 |
| 1894 # Git patches have a/ at the beginning of source paths. We strip that out | 1898 # Git patches have a/ at the beginning of source paths. We strip that out |
| 1895 # with a sed script rather than the -p flag to patch so we can feed either | 1899 # with a sed script rather than the -p flag to patch so we can feed either |
| 1896 # Git or svn-style patches into the same apply command. | 1900 # Git or svn-style patches into the same apply command. |
| 1897 # re.sub() should be used but flags=re.MULTILINE is only in python 2.7. | 1901 # re.sub() should be used but flags=re.MULTILINE is only in python 2.7. |
| 1898 try: | 1902 try: |
| 1899 patch_data = subprocess2.check_output( | 1903 patch_data = subprocess2.check_output( |
| 1900 ['sed', '-e', 's|^--- a/|--- |; s|^+++ b/|+++ |'], stdin=patch_data) | 1904 ['sed', '-e', 's|^--- a/|--- |; s|^+++ b/|+++ |'], stdin=patch_data) |
| 1901 except subprocess2.CalledProcessError: | 1905 except subprocess2.CalledProcessError: |
| 1902 DieWithError('Git patch mungling failed.') | 1906 DieWithError('Git patch mungling failed.') |
| 1903 logging.info(patch_data) | 1907 logging.info(patch_data) |
| 1904 env = os.environ.copy() | 1908 env = os.environ.copy() |
| 1905 # 'cat' is a magical git string that disables pagers on all platforms. | 1909 # 'cat' is a magical git string that disables pagers on all platforms. |
| 1906 env['GIT_PAGER'] = 'cat' | 1910 env['GIT_PAGER'] = 'cat' |
| 1907 | 1911 |
| 1908 # We use "git apply" to apply the patch instead of "patch" so that we can | 1912 # We use "git apply" to apply the patch instead of "patch" so that we can |
| 1909 # pick up file adds. | 1913 # pick up file adds. |
| 1910 # The --index flag means: also insert into the index (so we catch adds). | 1914 # The --index flag means: also insert into the index (so we catch adds). |
| 1911 cmd = ['git', 'apply', '--index', '-p0'] | 1915 cmd = ['git', 'apply', '--index', '-p0'] |
| 1912 if options.reject: | 1916 if reject: |
| 1913 cmd.append('--reject') | 1917 cmd.append('--reject') |
| 1914 elif IsGitVersionAtLeast('1.7.12'): | 1918 elif IsGitVersionAtLeast('1.7.12'): |
| 1915 cmd.append('--3way') | 1919 cmd.append('--3way') |
| 1916 try: | 1920 try: |
| 1917 subprocess2.check_call(cmd, env=env, | 1921 subprocess2.check_call(cmd, env=env, |
| 1918 stdin=patch_data, stdout=subprocess2.VOID) | 1922 stdin=patch_data, stdout=subprocess2.VOID) |
| 1919 except subprocess2.CalledProcessError: | 1923 except subprocess2.CalledProcessError: |
| 1920 DieWithError('Failed to apply the patch') | 1924 DieWithError('Failed to apply the patch') |
| 1921 | 1925 |
| 1922 # If we had an issue, commit the current state and register the issue. | 1926 # If we had an issue, commit the current state and register the issue. |
| 1923 if not options.nocommit: | 1927 if not nocommit: |
| 1924 RunGit(['commit', '-m', 'patch from issue %s' % issue]) | 1928 RunGit(['commit', '-m', 'patch from issue %s' % issue]) |
| 1925 cl = Changelist() | 1929 cl = Changelist() |
| 1926 cl.SetIssue(issue) | 1930 cl.SetIssue(issue) |
| 1927 cl.SetPatchset(patchset) | 1931 cl.SetPatchset(patchset) |
| 1928 print "Committed patch locally." | 1932 print "Committed patch locally." |
| 1929 else: | 1933 else: |
| 1930 print "Patch applied to index." | 1934 print "Patch applied to index." |
| 1931 return 0 | 1935 return 0 |
| 1932 | 1936 |
| 1933 | 1937 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 _, args = parser.parse_args(args) | 2125 _, args = parser.parse_args(args) |
| 2122 if args: | 2126 if args: |
| 2123 parser.error('Unrecognized args: %s' % ' '.join(args)) | 2127 parser.error('Unrecognized args: %s' % ' '.join(args)) |
| 2124 cl = Changelist() | 2128 cl = Changelist() |
| 2125 # Ensure there actually is an issue to close. | 2129 # Ensure there actually is an issue to close. |
| 2126 cl.GetDescription() | 2130 cl.GetDescription() |
| 2127 cl.CloseIssue() | 2131 cl.CloseIssue() |
| 2128 return 0 | 2132 return 0 |
| 2129 | 2133 |
| 2130 | 2134 |
| 2135 def CMDdiff(parser, args): |
| 2136 """shows differences between local tree and last upload.""" |
| 2137 cl = Changelist() |
| 2138 branch = cl.GetBranch() |
| 2139 TMP_BRANCH = 'git-cl-diff' |
| 2140 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() |
| 2141 |
| 2142 # Create a new branch based on the merge-base |
| 2143 RunGit(['checkout', '-q', '-b', TMP_BRANCH, base_branch]) |
| 2144 try: |
| 2145 # Patch in the latest changes from rietveld. |
| 2146 rtn = PatchIssue(cl.GetIssue(), False, False) |
| 2147 if rtn != 0: |
| 2148 return rtn |
| 2149 |
| 2150 # Switch back to starting brand and diff against the temporary |
| 2151 # branch containing the latest rietveld patch. |
| 2152 subprocess2.check_call(['git', 'diff', TMP_BRANCH, branch]) |
| 2153 finally: |
| 2154 RunGit(['checkout', '-q', branch]) |
| 2155 RunGit(['branch', '-D', TMP_BRANCH]) |
| 2156 |
| 2157 return 0 |
| 2158 |
| 2159 |
| 2131 def CMDowners(parser, args): | 2160 def CMDowners(parser, args): |
| 2132 """interactively find the owners for reviewing""" | 2161 """interactively find the owners for reviewing""" |
| 2133 parser.add_option( | 2162 parser.add_option( |
| 2134 '--no-color', | 2163 '--no-color', |
| 2135 action='store_true', | 2164 action='store_true', |
| 2136 help='Use this option to disable color output') | 2165 help='Use this option to disable color output') |
| 2137 options, args = parser.parse_args(args) | 2166 options, args = parser.parse_args(args) |
| 2138 | 2167 |
| 2139 author = RunGit(['config', 'user.email']).strip() or None | 2168 author = RunGit(['config', 'user.email']).strip() or None |
| 2140 | 2169 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 2285 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
| 2257 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 2286 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 2258 | 2287 |
| 2259 | 2288 |
| 2260 if __name__ == '__main__': | 2289 if __name__ == '__main__': |
| 2261 # These affect sys.stdout so do it outside of main() to simplify mocks in | 2290 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 2262 # unit testing. | 2291 # unit testing. |
| 2263 fix_encoding.fix_encoding() | 2292 fix_encoding.fix_encoding() |
| 2264 colorama.init() | 2293 colorama.init() |
| 2265 sys.exit(main(sys.argv[1:])) | 2294 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |