Chromium Code Reviews| Index: git_cl.py |
| diff --git a/git_cl.py b/git_cl.py |
| index c2675730cc4fc9c92de43750eca680381a6384bd..0e05c783a091f1a609dd0007476ef93b6ff688f0 100755 |
| --- a/git_cl.py |
| +++ b/git_cl.py |
| @@ -64,9 +64,8 @@ __version__ = '2.0' |
| COMMIT_BOT_EMAIL = 'commit-bot@chromium.org' |
| DEFAULT_SERVER = 'https://codereview.chromium.org' |
| -POSTUPSTREAM_HOOK_PATTERN = '.git/hooks/post-cl-%s' |
| +POSTUPSTREAM_HOOK_PATTERN = '.git/hooks/post-cl-land' |
| DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup' |
| -GIT_INSTRUCTIONS_URL = 'http://code.google.com/p/chromium/wiki/UsingGit' |
| REFS_THAT_ALIAS_TO_OTHER_REFS = { |
| 'refs/remotes/origin/lkgr': 'refs/remotes/origin/master', |
| 'refs/remotes/origin/lkcr': 'refs/remotes/origin/master', |
| @@ -558,48 +557,6 @@ def write_try_results_json(output_file, builds): |
| write_json(output_file, converted) |
| -def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): |
| - """Return the corresponding git ref if |base_url| together with |glob_spec| |
| - matches the full |url|. |
| - |
| - If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). |
| - """ |
| - fetch_suburl, as_ref = glob_spec.split(':') |
| - if allow_wildcards: |
| - glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) |
| - if glob_match: |
| - # Parse specs like "branches/*/src:refs/remotes/svn/*" or |
| - # "branches/{472,597,648}/src:refs/remotes/svn/*". |
| - branch_re = re.escape(base_url) |
| - if glob_match.group(1): |
| - branch_re += '/' + re.escape(glob_match.group(1)) |
| - wildcard = glob_match.group(2) |
| - if wildcard == '*': |
| - branch_re += '([^/]*)' |
| - else: |
| - # Escape and replace surrounding braces with parentheses and commas |
| - # with pipe symbols. |
| - wildcard = re.escape(wildcard) |
| - wildcard = re.sub('^\\\\{', '(', wildcard) |
| - wildcard = re.sub('\\\\,', '|', wildcard) |
| - wildcard = re.sub('\\\\}$', ')', wildcard) |
| - branch_re += wildcard |
| - if glob_match.group(3): |
| - branch_re += re.escape(glob_match.group(3)) |
| - match = re.match(branch_re, url) |
| - if match: |
| - return re.sub('\*$', match.group(1), as_ref) |
| - |
| - # Parse specs like "trunk/src:refs/remotes/origin/trunk". |
| - if fetch_suburl: |
| - full_url = base_url + '/' + fetch_suburl |
| - else: |
| - full_url = base_url |
| - if full_url == url: |
| - return as_ref |
| - return None |
| - |
| - |
| def print_stats(similarity, find_copies, args): |
| """Prints statistics about the change to the user.""" |
| # --no-ext-diff is broken in some versions of Git, so try to work around |
| @@ -634,8 +591,6 @@ class Settings(object): |
| self.default_server = None |
| self.cc = None |
| self.root = None |
| - self.is_git_svn = None |
| - self.svn_branch = None |
| self.tree_status_url = None |
| self.viewvc_url = None |
| self.updated = False |
| @@ -698,87 +653,6 @@ class Settings(object): |
| return mirror |
| return None |
| - def GetIsGitSvn(self): |
| - """Return true if this repo looks like it's using git-svn.""" |
| - if self.is_git_svn is None: |
| - if self.GetPendingRefPrefix(): |
| - # If PENDING_REF_PREFIX is set then it's a pure git repo no matter what. |
| - self.is_git_svn = False |
| - else: |
| - # If you have any "svn-remote.*" config keys, we think you're using svn. |
| - self.is_git_svn = RunGitWithCode( |
| - ['config', '--local', '--get-regexp', r'^svn-remote\.'])[0] == 0 |
| - return self.is_git_svn |
| - |
| - def GetSVNBranch(self): |
| - if self.svn_branch is None: |
| - if not self.GetIsGitSvn(): |
| - DieWithError('Repo doesn\'t appear to be a git-svn repo.') |
| - |
| - # Try to figure out which remote branch we're based on. |
| - # Strategy: |
| - # 1) iterate through our branch history and find the svn URL. |
| - # 2) find the svn-remote that fetches from the URL. |
| - |
| - # regexp matching the git-svn line that contains the URL. |
| - git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) |
| - |
| - # We don't want to go through all of history, so read a line from the |
| - # pipe at a time. |
| - # The -100 is an arbitrary limit so we don't search forever. |
| - cmd = ['git', 'log', '-100', '--pretty=medium'] |
| - proc = subprocess2.Popen(cmd, stdout=subprocess2.PIPE, |
| - env=GetNoGitPagerEnv()) |
| - url = None |
| - for line in proc.stdout: |
| - match = git_svn_re.match(line) |
| - if match: |
| - url = match.group(1) |
| - proc.stdout.close() # Cut pipe. |
| - break |
| - |
| - if url: |
| - svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$') |
| - remotes = RunGit(['config', '--get-regexp', |
| - r'^svn-remote\..*\.url']).splitlines() |
| - for remote in remotes: |
| - match = svn_remote_re.match(remote) |
| - if match: |
| - remote = match.group(1) |
| - base_url = match.group(2) |
| - rewrite_root = RunGit( |
| - ['config', 'svn-remote.%s.rewriteRoot' % remote], |
| - error_ok=True).strip() |
| - if rewrite_root: |
| - base_url = rewrite_root |
| - fetch_spec = RunGit( |
| - ['config', 'svn-remote.%s.fetch' % remote], |
| - error_ok=True).strip() |
| - if fetch_spec: |
| - self.svn_branch = MatchSvnGlob(url, base_url, fetch_spec, False) |
| - if self.svn_branch: |
| - break |
| - branch_spec = RunGit( |
| - ['config', 'svn-remote.%s.branches' % remote], |
| - error_ok=True).strip() |
| - if branch_spec: |
| - self.svn_branch = MatchSvnGlob(url, base_url, branch_spec, True) |
| - if self.svn_branch: |
| - break |
| - tag_spec = RunGit( |
| - ['config', 'svn-remote.%s.tags' % remote], |
| - error_ok=True).strip() |
| - if tag_spec: |
| - self.svn_branch = MatchSvnGlob(url, base_url, tag_spec, True) |
| - if self.svn_branch: |
| - break |
| - |
| - if not self.svn_branch: |
| - DieWithError('Can\'t guess svn branch -- try specifying it on the ' |
| - 'command line') |
| - |
| - return self.svn_branch |
| - |
| def GetTreeStatusUrl(self, error_ok=False): |
| if not self.tree_status_url: |
| error_message = ('You must configure your tree status URL by running ' |
| @@ -1129,28 +1003,19 @@ class Changelist(object): |
| if upstream_branch: |
| remote = RunGit(['config', 'rietveld.upstream-remote']).strip() |
| else: |
| - # Fall back on trying a git-svn upstream branch. |
| - if settings.GetIsGitSvn(): |
| - upstream_branch = settings.GetSVNBranch() |
| + # Else, try to guess the origin remote. |
| + remote_branches = RunGit(['branch', '-r']).split() |
| + if 'origin/master' in remote_branches: |
| + # Fall back on origin/master if it exits. |
| + remote = 'origin' |
| + upstream_branch = 'refs/heads/master' |
| else: |
| - # Else, try to guess the origin remote. |
| - remote_branches = RunGit(['branch', '-r']).split() |
| - if 'origin/master' in remote_branches: |
| - # Fall back on origin/master if it exits. |
| - remote = 'origin' |
| - upstream_branch = 'refs/heads/master' |
| - elif 'origin/trunk' in remote_branches: |
| - # Fall back on origin/trunk if it exists. Generally a shared |
| - # git-svn clone |
| - remote = 'origin' |
| - upstream_branch = 'refs/heads/trunk' |
| - else: |
| - DieWithError( |
| - 'Unable to determine default branch to diff against.\n' |
| - 'Either pass complete "git diff"-style arguments, like\n' |
| - ' git cl upload origin/master\n' |
| - 'or verify this branch is set up to track another \n' |
| - '(via the --track argument to "git checkout -b ...").') |
| + DieWithError( |
| + 'Unable to determine default branch to diff against.\n' |
| + 'Either pass complete "git diff"-style arguments, like\n' |
| + ' git cl upload origin/master\n' |
| + 'or verify this branch is set up to track another \n' |
| + '(via the --track argument to "git checkout -b ...").') |
| return remote, upstream_branch |
| @@ -1189,17 +1054,11 @@ class Changelist(object): |
| remote, = remotes |
| elif 'origin' in remotes: |
| remote = 'origin' |
| - logging.warning('Could not determine which remote this change is ' |
| - 'associated with, so defaulting to "%s". This may ' |
| - 'not be what you want. You may prevent this message ' |
| - 'by running "git svn info" as documented here: %s', |
| - self._remote, |
| - GIT_INSTRUCTIONS_URL) |
| + logging.warn('Could not determine which remote this change is ' |
| + 'associated with, so defaulting to "%s".' % self._remote) |
| else: |
| logging.warn('Could not determine which remote this change is ' |
| - 'associated with. You may prevent this message by ' |
| - 'running "git svn info" as documented here: %s', |
| - GIT_INSTRUCTIONS_URL) |
| + 'associated with.') |
| branch = 'HEAD' |
| if branch.startswith('refs/remotes'): |
| self._remote = (remote, branch) |
| @@ -1258,19 +1117,6 @@ class Changelist(object): |
| """ |
| return self._GitGetBranchConfigValue('base-url') |
| - def GetGitSvnRemoteUrl(self): |
| - """Return the configured git-svn remote URL parsed from git svn info. |
| - |
| - Returns None if it is not set. |
| - """ |
| - # URL is dependent on the current directory. |
| - data = RunGit(['svn', 'info'], cwd=settings.GetRoot()) |
| - if data: |
| - keys = dict(line.split(': ', 1) for line in data.splitlines() |
| - if ': ' in line) |
| - return keys.get('URL', None) |
| - return None |
| - |
| def GetRemoteUrl(self): |
| """Return the configured remote URL, e.g. 'git://example.org/foo.git/'. |
| @@ -2041,12 +1887,9 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase): |
| # projects that have their source spread across multiple repos. |
| remote_url = self.GetGitBaseUrlFromConfig() |
| if not remote_url: |
| - if settings.GetIsGitSvn(): |
| - remote_url = self.GetGitSvnRemoteUrl() |
| - else: |
| - if self.GetRemoteUrl() and '/' in self.GetUpstreamBranch(): |
| - remote_url = '%s@%s' % (self.GetRemoteUrl(), |
| - self.GetUpstreamBranch().split('/')[-1]) |
| + if self.GetRemoteUrl() and '/' in self.GetUpstreamBranch(): |
| + remote_url = '%s@%s' % (self.GetRemoteUrl(), |
| + self.GetUpstreamBranch().split('/')[-1]) |
| if remote_url: |
| remote, remote_branch = self.GetRemoteBranch() |
| target_ref = GetTargetRef(remote, remote_branch, options.target_branch, |
| @@ -3984,14 +3827,6 @@ def CMDupload(parser, args): |
| return cl.CMDUpload(options, args, orig_args) |
| -def IsSubmoduleMergeCommit(ref): |
| - # When submodules are added to the repo, we expect there to be a single |
| - # non-git-svn merge commit at remote HEAD with a signature comment. |
| - pattern = '^SVN changes up to revision [0-9]*$' |
| - cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref] |
| - return RunGit(cmd) != '' |
| - |
| - |
| def SendUpstream(parser, args, cmd): |
| """Common code for CMDland and CmdDCommit |
| @@ -4045,7 +3880,7 @@ def SendUpstream(parser, args, cmd): |
| current = cl.GetBranch() |
| remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
| - if not settings.GetIsGitSvn() and remote == '.': |
| + if remote == '.': |
| print() |
| print('Attempting to push branch %r into another local branch!' % current) |
| print() |
| @@ -4058,7 +3893,7 @@ def SendUpstream(parser, args, cmd): |
| print(' Current parent: %r' % upstream_branch) |
| return 1 |
| - if not args or cmd == 'land': |
| + if not args: |
| # Default to merging against our best guess of the upstream branch. |
| args = [cl.GetUpstreamBranch()] |
| @@ -4068,9 +3903,8 @@ def SendUpstream(parser, args, cmd): |
| return 1 |
| base_branch = args[0] |
| - base_has_submodules = IsSubmoduleMergeCommit(base_branch) |
| - if git_common.is_dirty_git_tree(cmd): |
| + if git_common.is_dirty_git_tree('land'): |
| return 1 |
| # This rev-list syntax means "show all commits not in my branch that |
| @@ -4080,30 +3914,9 @@ def SendUpstream(parser, args, cmd): |
| if upstream_commits: |
| print('Base branch "%s" has %d commits ' |
| 'not in this branch.' % (base_branch, len(upstream_commits))) |
| - print('Run "git merge %s" before attempting to %s.' % (base_branch, cmd)) |
| + print('Run "git merge %s" before attempting to land.' % base_branch) |
| return 1 |
| - # This is the revision `svn dcommit` will commit on top of. |
| - svn_head = None |
| - if cmd == 'dcommit' or base_has_submodules: |
| - svn_head = RunGit(['log', '--grep=^git-svn-id:', '-1', |
| - '--pretty=format:%H']) |
| - |
| - if cmd == 'dcommit': |
| - # If the base_head is a submodule merge commit, the first parent of the |
| - # base_head should be a git-svn commit, which is what we're interested in. |
| - base_svn_head = base_branch |
| - if base_has_submodules: |
| - base_svn_head += '^1' |
| - |
| - extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head]) |
| - if extra_commits: |
| - print('This branch has %d additional commits not upstreamed yet.' |
| - % len(extra_commits.splitlines())) |
| - print('Upstream "%s" or rebase this branch on top of the upstream trunk ' |
| - 'before attempting to %s.' % (base_branch, cmd)) |
| - return 1 |
| - |
| merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip() |
| if not options.bypass_hooks: |
| author = None |
| @@ -4121,11 +3934,11 @@ def SendUpstream(parser, args, cmd): |
| status = GetTreeStatus() |
| if 'closed' == status: |
| print('The tree is closed. Please wait for it to reopen. Use ' |
| - '"git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) |
| + '"git cl land --bypass-hooks" to commit on a closed tree.') |
| return 1 |
| elif 'unknown' == status: |
| print('Unable to determine tree status. Please verify manually and ' |
| - 'use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) |
| + 'use "git cl land --bypass-hooks" to commit on a closed tree.') |
| return 1 |
| change_desc = ChangeDescription(options.message) |
| @@ -4166,9 +3979,7 @@ def SendUpstream(parser, args, cmd): |
| # We want to squash all this branch's commits into one commit with the proper |
| # description. We do this by doing a "reset --soft" to the base branch (which |
| - # keeps the working copy the same), then dcommitting that. If origin/master |
| - # has a submodule merge commit, we'll also need to cherry-pick the squashed |
| - # commit onto a branch based on the git-svn head. |
| + # keeps the working copy the same), then dcommitting that. |
| MERGE_BRANCH = 'git-cl-commit' |
| CHERRY_PICK_BRANCH = 'git-cl-cherry-pick' |
| # Delete the branches if they exist. |
| @@ -4203,56 +4014,30 @@ def SendUpstream(parser, args, cmd): |
| ]) |
| else: |
| RunGit(['commit', '-m', commit_desc.description]) |
| - if base_has_submodules: |
| - cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() |
| - RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) |
| - RunGit(['checkout', CHERRY_PICK_BRANCH]) |
| - RunGit(['cherry-pick', cherry_pick_commit]) |
| - if cmd == 'land': |
| - remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
| - mirror = settings.GetGitMirror(remote) |
| - pushurl = mirror.url if mirror else remote |
| - pending_prefix = settings.GetPendingRefPrefix() |
| - if not pending_prefix or branch.startswith(pending_prefix): |
| - # If not using refs/pending/heads/* at all, or target ref is already set |
| - # to pending, then push to the target ref directly. |
| - retcode, output = RunGitWithCode( |
| - ['push', '--porcelain', pushurl, 'HEAD:%s' % branch]) |
| - pushed_to_pending = pending_prefix and branch.startswith(pending_prefix) |
| - else: |
| - # Cherry-pick the change on top of pending ref and then push it. |
| - assert branch.startswith('refs/'), branch |
| - assert pending_prefix[-1] == '/', pending_prefix |
| - pending_ref = pending_prefix + branch[len('refs/'):] |
| - retcode, output = PushToGitPending(pushurl, pending_ref) |
| - pushed_to_pending = (retcode == 0) |
| - if retcode == 0: |
| - revision = RunGit(['rev-parse', 'HEAD']).strip() |
| + remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
| + mirror = settings.GetGitMirror(remote) |
| + pushurl = mirror.url if mirror else remote |
| + pending_prefix = settings.GetPendingRefPrefix() |
| + if not pending_prefix or branch.startswith(pending_prefix): |
| + # If not using refs/pending/heads/* at all, or target ref is already set |
| + # to pending, then push to the target ref directly. |
| + retcode, output = RunGitWithCode( |
| + ['push', '--porcelain', pushurl, 'HEAD:%s' % branch]) |
| + pushed_to_pending = pending_prefix and branch.startswith(pending_prefix) |
| else: |
| - # dcommit the merge branch. |
| - cmd_args = [ |
| - 'svn', 'dcommit', |
| - '-C%s' % options.similarity, |
| - '--no-rebase', '--rmdir', |
| - ] |
| - if settings.GetForceHttpsCommitUrl(): |
| - # Allow forcing https commit URLs for some projects that don't allow |
| - # committing to http URLs (like Google Code). |
| - remote_url = cl.GetGitSvnRemoteUrl() |
| - if urlparse.urlparse(remote_url).scheme == 'http': |
| - remote_url = remote_url.replace('http://', 'https://') |
| - cmd_args.append('--commit-url=%s' % remote_url) |
| - _, output = RunGitWithCode(cmd_args) |
| - if 'Committed r' in output: |
| - revision = re.match( |
| - '.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1) |
| + # Cherry-pick the change on top of pending ref and then push it. |
| + assert branch.startswith('refs/'), branch |
| + assert pending_prefix[-1] == '/', pending_prefix |
| + pending_ref = pending_prefix + branch[len('refs/'):] |
| + retcode, output = PushToGitPending(pushurl, pending_ref) |
| + pushed_to_pending = (retcode == 0) |
| + if retcode == 0: |
| + revision = RunGit(['rev-parse', 'HEAD']).strip() |
| logging.debug(output) |
| finally: |
| # And then swap back to the original branch and clean up. |
| RunGit(['checkout', '-q', cl.GetBranch()]) |
| RunGit(['branch', '-D', MERGE_BRANCH]) |
| - if base_has_submodules: |
| - RunGit(['branch', '-D', CHERRY_PICK_BRANCH]) |
| if not revision: |
| print('Failed to push. If this persists, please file a bug.') |
| @@ -4297,7 +4082,7 @@ def SendUpstream(parser, args, cmd): |
| print('It will show up on %s in ~1 min, once it gets a Cr-Commit-Position ' |
| 'footer.' % branch) |
| - hook = POSTUPSTREAM_HOOK_PATTERN % cmd |
| + hook = POSTUPSTREAM_HOOK_PATTERN |
| if os.path.isfile(hook): |
| RunCommand([hook, merge_base], error_ok=True) |
| @@ -4399,38 +4184,15 @@ def IsFatalPushFailure(push_stdout): |
| @subcommand.usage('[upstream branch to apply against]') |
| def CMDdcommit(parser, args): |
| - """Commits the current changelist via git-svn.""" |
| - if not settings.GetIsGitSvn(): |
| - if git_footers.get_footer_svn_id(): |
| - # If it looks like previous commits were mirrored with git-svn. |
| - message = """This repository appears to be a git-svn mirror, but we |
| -don't support git-svn mirrors anymore.""" |
| - else: |
| - message = """This doesn't appear to be an SVN repository. |
| -If your project has a true, writeable git repository, you probably want to run |
| -'git cl land' instead. |
| -If your project has a git mirror of an upstream SVN master, you probably need |
| -to run 'git svn init'. |
| - |
| -Using the wrong command might cause your commit to appear to succeed, and the |
| -review to be closed, without actually landing upstream. If you choose to |
| -proceed, please verify that the commit lands upstream as expected.""" |
| - print(message) |
| - ask_for_data('[Press enter to dcommit or ctrl-C to quit]') |
| - print('WARNING: chrome infrastructure is migrating SVN repos to Git.\n' |
| - 'Please let us know of this project you are committing to:' |
| - ' http://crbug.com/600451') |
| - return SendUpstream(parser, args, 'dcommit') |
| + """DEPRECATED: Used to commit the current changelist via git-svn.""" |
| + message = ('git-cl no longer supports committing to SVN repositories via' |
| + 'git-svn. You probably want to use `git cl land` instead.') |
| + print(message) |
|
tandrii(chromium)
2016/10/06 08:04:01
I'd add return 1 so command results in error.
agable
2016/10/06 21:43:15
Done.
|
| @subcommand.usage('[upstream branch to apply against]') |
| def CMDland(parser, args): |
| """Commits the current changelist via git.""" |
| - if settings.GetIsGitSvn() or git_footers.get_footer_svn_id(): |
| - print('This appears to be an SVN repository.') |
| - print('Are you sure you didn\'t mean \'git cl dcommit\'?') |
| - print('(Ignore if this is the first commit after migrating from svn->git)') |
| - ask_for_data('[Press enter to push or ctrl-C to quit]') |
| return SendUpstream(parser, args, 'land') |
| @@ -4524,16 +4286,6 @@ def CMDpatch(parser, args): |
| options.directory) |
| -def CMDrebase(parser, args): |
| - """Rebases current branch on top of svn repo.""" |
| - # Provide a wrapper for git svn rebase to help avoid accidental |
| - # git svn dcommit. |
| - # It's the only command that doesn't use parser at all since we just defer |
| - # execution to git-svn. |
| - |
| - return RunGitWithCode(['svn', 'rebase'] + args)[1] |
| - |
| - |
| def GetTreeStatus(url=None): |
| """Fetches the tree status and returns either 'open', 'closed', |
| 'unknown' or 'unset'.""" |