Remove SVN (and dcommit) support from git-cl

BUG=638750

Change-Id: I9ebe4ff861a37433209b66f4050370b49f17cdc7
Reviewed-on: https://chromium-review.googlesource.com/419661
Commit-Queue: Aaron Gable <agable@chromium.org>
Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>
changes/61/419661/5
Aaron Gable 10 years ago committed by Commit Bot
parent dd013e2b68
commit 1bc7bfe5d9

@ -86,12 +86,11 @@ def RunGitClTests(input_api, output_api):
server.start_server()
test_path = input_api.os_path.abspath(
input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'))
# test-lib.sh is not an actual test so it should not be run.
NON_TEST_FILES = ('test-lib.sh')
for test in input_api.os_listdir(test_path):
# test-lib.sh is not an actual test so it should not be run. The other
# tests are tests known to fail.
DISABLED_TESTS = (
'owners.sh', 'push-from-logs.sh', 'rename.sh', 'test-lib.sh')
if test in DISABLED_TESTS or not test.endswith('.sh'):
if test in NON_TEST_FILES or not test.endswith('.sh'):
continue
print('Running %s' % test)

@ -66,9 +66,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 = '.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',
@ -701,48 +700,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
@ -776,8 +733,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
@ -839,87 +794,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 '
@ -1397,28 +1271,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
@ -1457,17 +1322,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)
@ -1526,19 +1385,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/'.
@ -2293,8 +2139,12 @@ class _RietveldChangelistImpl(_ChangelistCodereviewBase):
else:
if options.title is not None:
upload_args.extend(['--title', options.title])
message = (options.title or options.message or
CreateDescriptionFromLog(args))
if options.message:
message = options.message
else:
message = CreateDescriptionFromLog(args)
if options.title:
message = options.title + '\n\n' + message
change_desc = ChangeDescription(message)
if options.reviewers or options.tbr_owners:
change_desc.update_reviewers(options.reviewers,
@ -2343,12 +2193,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,
@ -4209,7 +4056,7 @@ def CMDlint(parser, args):
def CMDpresubmit(parser, args):
"""Runs presubmit tests on the current changelist."""
parser.add_option('-u', '--upload', action='store_true',
help='Run upload hook instead of the push/dcommit hook')
help='Run upload hook instead of the push hook')
parser.add_option('-f', '--force', action='store_true',
help='Run checks even if tree is dirty')
auth.add_auth_options(parser)
@ -4354,14 +4201,15 @@ def CMDupload(parser, args):
help='bypass watchlists auto CC-ing reviewers')
parser.add_option('-f', action='store_true', dest='force',
help="force yes to questions (don't prompt)")
parser.add_option('-m', dest='message', help='message for patchset')
parser.add_option('--message', '-m', dest='message',
help='message for patchset')
parser.add_option('-b', '--bug',
help='pre-populate the bug number(s) for this issue. '
'If several, separate with commas')
parser.add_option('--message-file', dest='message_file',
help='file which contains message for patchset')
parser.add_option('-t', dest='title',
help='title for patchset (Rietveld only)')
parser.add_option('--title', '-t', dest='title',
help='title for patchset')
parser.add_option('-r', '--reviewers',
action='append', default=[],
help='reviewer email addresses')
@ -4433,16 +4281,111 @@ 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 WaitForRealCommit(remote, pushed_commit, local_base_ref, real_ref):
print()
print('Waiting for commit to be landed on %s...' % real_ref)
print('(If you are impatient, you may Ctrl-C once without harm)')
target_tree = RunGit(['rev-parse', '%s:' % pushed_commit]).strip()
current_rev = RunGit(['rev-parse', local_base_ref]).strip()
mirror = settings.GetGitMirror(remote)
loop = 0
while True:
sys.stdout.write('fetching (%d)... \r' % loop)
sys.stdout.flush()
loop += 1
if mirror:
mirror.populate()
RunGit(['retry', 'fetch', remote, real_ref], stderr=subprocess2.VOID)
to_rev = RunGit(['rev-parse', 'FETCH_HEAD']).strip()
commits = RunGit(['rev-list', '%s..%s' % (current_rev, to_rev)])
for commit in commits.splitlines():
if RunGit(['rev-parse', '%s:' % commit]).strip() == target_tree:
print('Found commit on %s' % real_ref)
return commit
current_rev = to_rev
def PushToGitPending(remote, pending_ref):
"""Fetches pending_ref, cherry-picks current HEAD on top of it, pushes.
Returns:
(retcode of last operation, output log of last operation).
"""
assert pending_ref.startswith('refs/'), pending_ref
local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):]
cherry = RunGit(['rev-parse', 'HEAD']).strip()
code = 0
out = ''
max_attempts = 3
attempts_left = max_attempts
while attempts_left:
if attempts_left != max_attempts:
print('Retrying, %d attempts left...' % (attempts_left - 1,))
attempts_left -= 1
# Fetch. Retry fetch errors.
print('Fetching pending ref %s...' % pending_ref)
code, out = RunGitWithCode(
['retry', 'fetch', remote, '+%s:%s' % (pending_ref, local_pending_ref)])
if code:
print('Fetch failed with exit code %d.' % code)
if out.strip():
print(out.strip())
continue
# Try to cherry pick. Abort on merge conflicts.
print('Cherry-picking commit on top of pending ref...')
RunGitWithCode(['checkout', local_pending_ref], suppress_stderr=True)
code, out = RunGitWithCode(['cherry-pick', cherry])
if code:
print('Your patch doesn\'t apply cleanly to ref \'%s\', '
'the following files have merge conflicts:' % pending_ref)
print(RunGit(['diff', '--name-status', '--diff-filter=U']).strip())
print('Please rebase your patch and try again.')
RunGitWithCode(['cherry-pick', '--abort'])
return code, out
# Applied cleanly, try to push now. Retry on error (flake or non-ff push).
print('Pushing commit to %s... It can take a while.' % pending_ref)
code, out = RunGitWithCode(
['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref])
if code == 0:
# Success.
print('Commit pushed to pending ref successfully!')
return code, out
print('Push failed with exit code %d.' % code)
if out.strip():
print(out.strip())
if IsFatalPushFailure(out):
print('Fatal push error. Make sure your .netrc credentials and git '
'user.email are correct and you have push access to the repo.')
return code, out
print('All attempts to push to pending ref failed.')
return code, out
def IsFatalPushFailure(push_stdout):
"""True if retrying push won't help."""
return '(prohibited by Gerrit)' in push_stdout
@subcommand.usage('DEPRECATED')
def CMDdcommit(parser, args):
"""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)
return 1
def SendUpstream(parser, args, cmd):
"""Common code for CMDland and CmdDCommit
@subcommand.usage('[upstream branch to apply against]')
def CMDland(parser, args):
"""Commits the current changelist via git.
In case of Gerrit, uses Gerrit REST api to "submit" the issue, which pushes
upstream and closes the issue automatically and atomically.
@ -4494,7 +4437,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()
@ -4507,7 +4450,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()]
@ -4517,9 +4460,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
@ -4529,30 +4471,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
@ -4570,11 +4491,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)
@ -4614,9 +4535,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 landing that.
MERGE_BRANCH = 'git-cl-commit'
CHERRY_PICK_BRANCH = 'git-cl-cherry-pick'
# Delete the branches if they exist.
@ -4651,84 +4570,60 @@ 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())
logging.debug('remote: %s, branch %s', remote, branch)
mirror = settings.GetGitMirror(remote)
if mirror:
pushurl = mirror.url
git_numberer = _GitNumbererState.load(pushurl, branch)
else:
pushurl = remote # Usually, this is 'origin'.
git_numberer = _GitNumbererState.load(
RunGit(['config', 'remote.%s.url' % remote]).strip(), branch)
pending_prefix = git_numberer.pending_prefix
if git_numberer.should_add_git_number:
# TODO(tandrii): run git fetch in a loop + autorebase when there there
# is no pending ref to push to?
logging.debug('Adding git number footers')
parent_msg = RunGit(['show', '-s', '--format=%B', merge_base]).strip()
commit_desc.update_with_git_number_footers(merge_base, parent_msg,
branch)
# Ensure timestamps are monotonically increasing.
timestamp = max(1 + _get_committer_timestamp(merge_base),
_get_committer_timestamp('HEAD'))
_git_amend_head(commit_desc.description, timestamp)
change_desc = ChangeDescription(commit_desc.description)
# If gnumbd is sitll ON and we ultimately push to branch with
# pending_prefix, gnumbd will modify footers we've just inserted with
# 'Original-', which is annoying but still technically correct.
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.
# NB(tandrii): I think branch.startswith(pending_prefix) never happens
# in practise. I really tried to create a new branch tracking
# refs/pending/heads/master directly and git cl land failed long before
# reaching this. Disagree? Comment on http://crbug.com/642493.
if pending_prefix:
print('\n\nYOU GOT A CHANCE TO WIN A FREE GIFT!\n\n'
'Grab your .git/config, add instructions how to reproduce '
'this, and post it to http://crbug.com/642493.\n'
'The first reporter gets a free "Black Swan" book from '
'tandrii@\n\n')
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)
if mirror:
pushurl = mirror.url
git_numberer = _GitNumbererState.load(pushurl, branch)
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)
pushurl = remote # Usually, this is 'origin'.
git_numberer = _GitNumbererState.load(
RunGit(['config', 'remote.%s.url' % remote]).strip(), branch)
if git_numberer.should_add_git_number:
# TODO(tandrii): run git fetch in a loop + autorebase when there there
# is no pending ref to push to?
logging.debug('Adding git number footers')
parent_msg = RunGit(['show', '-s', '--format=%B', merge_base]).strip()
commit_desc.update_with_git_number_footers(merge_base, parent_msg,
branch)
# Ensure timestamps are monotonically increasing.
timestamp = max(1 + _get_committer_timestamp(merge_base),
_get_committer_timestamp('HEAD'))
_git_amend_head(commit_desc.description, timestamp)
change_desc = ChangeDescription(commit_desc.description)
# If gnumbd is sitll ON and we ultimately push to branch with
# pending_prefix, gnumbd will modify footers we've just inserted with
# 'Original-', which is annoying but still technically correct.
pending_prefix = git_numberer.pending_prefix
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.
# NB(tandrii): I think branch.startswith(pending_prefix) never happens
# in practise. I really tried to create a new branch tracking
# refs/pending/heads/master directly and git cl land failed long before
# reaching this. Disagree? Comment on http://crbug.com/642493.
if pending_prefix:
print('\n\nYOU GOT A CHANCE TO WIN A FREE GIFT!\n\n'
'Grab your .git/config, add instructions how to reproduce '
'this, and post it to http://crbug.com/642493.\n'
'The first reporter gets a free "Black Swan" book from '
'tandrii@\n\n')
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()
logging.debug(output)
except: # pylint: disable=bare-except
if _IS_BEING_TESTED:
@ -4740,8 +4635,6 @@ def SendUpstream(parser, args, cmd):
# 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.')
@ -4786,143 +4679,12 @@ 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
if os.path.isfile(hook):
RunCommand([hook, merge_base], error_ok=True)
if os.path.isfile(POSTUPSTREAM_HOOK):
RunCommand([POSTUPSTREAM_HOOK, merge_base], error_ok=True)
return 1 if killed else 0
def WaitForRealCommit(remote, pushed_commit, local_base_ref, real_ref):
print()
print('Waiting for commit to be landed on %s...' % real_ref)
print('(If you are impatient, you may Ctrl-C once without harm)')
target_tree = RunGit(['rev-parse', '%s:' % pushed_commit]).strip()
current_rev = RunGit(['rev-parse', local_base_ref]).strip()
mirror = settings.GetGitMirror(remote)
loop = 0
while True:
sys.stdout.write('fetching (%d)... \r' % loop)
sys.stdout.flush()
loop += 1
if mirror:
mirror.populate()
RunGit(['retry', 'fetch', remote, real_ref], stderr=subprocess2.VOID)
to_rev = RunGit(['rev-parse', 'FETCH_HEAD']).strip()
commits = RunGit(['rev-list', '%s..%s' % (current_rev, to_rev)])
for commit in commits.splitlines():
if RunGit(['rev-parse', '%s:' % commit]).strip() == target_tree:
print('Found commit on %s' % real_ref)
return commit
current_rev = to_rev
def PushToGitPending(remote, pending_ref):
"""Fetches pending_ref, cherry-picks current HEAD on top of it, pushes.
Returns:
(retcode of last operation, output log of last operation).
"""
assert pending_ref.startswith('refs/'), pending_ref
local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):]
cherry = RunGit(['rev-parse', 'HEAD']).strip()
code = 0
out = ''
max_attempts = 3
attempts_left = max_attempts
while attempts_left:
if attempts_left != max_attempts:
print('Retrying, %d attempts left...' % (attempts_left - 1,))
attempts_left -= 1
# Fetch. Retry fetch errors.
print('Fetching pending ref %s...' % pending_ref)
code, out = RunGitWithCode(
['retry', 'fetch', remote, '+%s:%s' % (pending_ref, local_pending_ref)])
if code:
print('Fetch failed with exit code %d.' % code)
if out.strip():
print(out.strip())
continue
# Try to cherry pick. Abort on merge conflicts.
print('Cherry-picking commit on top of pending ref...')
RunGitWithCode(['checkout', local_pending_ref], suppress_stderr=True)
code, out = RunGitWithCode(['cherry-pick', cherry])
if code:
print('Your patch doesn\'t apply cleanly to ref \'%s\', '
'the following files have merge conflicts:' % pending_ref)
print(RunGit(['diff', '--name-status', '--diff-filter=U']).strip())
print('Please rebase your patch and try again.')
RunGitWithCode(['cherry-pick', '--abort'])
return code, out
# Applied cleanly, try to push now. Retry on error (flake or non-ff push).
print('Pushing commit to %s... It can take a while.' % pending_ref)
code, out = RunGitWithCode(
['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref])
if code == 0:
# Success.
print('Commit pushed to pending ref successfully!')
return code, out
print('Push failed with exit code %d.' % code)
if out.strip():
print(out.strip())
if IsFatalPushFailure(out):
print('Fatal push error. Make sure your .netrc credentials and git '
'user.email are correct and you have push access to the repo.')
return code, out
print('All attempts to push to pending ref failed.')
return code, out
def IsFatalPushFailure(push_stdout):
"""True if retrying push won't help."""
return '(prohibited by Gerrit)' in 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')
@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')
@subcommand.usage('<patch url or issue id or issue url>')
def CMDpatch(parser, args):
"""Patches in a code review."""
@ -5013,16 +4775,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'."""

@ -10,12 +10,12 @@ set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
(
set -e
cd git-svn
cd git_checkout
git config rietveld.server localhost:10000
# Create a branch and give it an issue.

@ -8,13 +8,13 @@ set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
(
set -e
cd git-svn
git checkout -q -b work
cd git_checkout
git checkout -q --track -b work origin
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
echo "some other work done on a branch" >> test
@ -32,7 +32,7 @@ setup_gitsvn
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl status now knows the issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
@ -45,19 +45,21 @@ setup_gitsvn
--data-urlencode xsrf_token="$(print_xsrf_token)" \
$URL/edit
test_expect_success "git-cl dcommits ok" \
"$GIT_CL dcommit -f --no-oauth2"
test_expect_success "git-cl land ok" \
"$GIT_CL land -f --no-oauth2"
test_expect_success "branch still has an issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
git checkout -q master
git svn -q rebase >/dev/null 2>&1
test_expect_success "dcommitted code has proper description" \
git checkout -q master > /dev/null 2>&1
git pull -q > /dev/null 2>&1
test_expect_success "committed code has proper description" \
"git show | grep -q 'foo-quux'"
test_expect_success "upstream svn has our commit" \
"svn log $REPO_URL 2>/dev/null | grep -q 'foo-quux'"
cd $GITREPO_PATH
test_expect_success "upstream repo has our commit" \
"git log master 2>/dev/null | grep -q 'foo-quux'"
)
SUCCESS=$?

@ -635,12 +635,7 @@ class TestGitCl(TestCase):
((['git', 'config', 'core.editor'],), ''),
] + cc_call + private_call + [
((['git', 'config', 'branch.master.base-url'],), ''),
((['git', 'config', 'rietveld.pending-ref-prefix'],), ''),
((['git',
'config', '--local', '--get-regexp', '^svn-remote\\.'],),
(('', None), 0)),
((['git', 'rev-parse', '--show-cdup'],), ''),
((['git', 'svn', 'info'],), ''),
((['git', 'config', 'remote.origin.url'],), ''),
((['git', 'config', 'rietveld.project'],), ''),
((['git', 'config', 'branch.master.rietveldissue', '1'],), ''),
((['git', 'config', 'branch.master.rietveldserver',
@ -685,106 +680,6 @@ class TestGitCl(TestCase):
'refs/remotes/origin/master'],), ''),
]
@classmethod
def _dcommit_calls_1(cls):
return [
((['git', 'config', 'rietveld.autoupdate'],),
''),
((['git', 'config', 'rietveld.pending-ref-prefix'],),
''),
((['git',
'config', '--local', '--get-regexp', '^svn-remote\\.'],),
((('svn-remote.svn.url svn://svn.chromium.org/chrome\n'
'svn-remote.svn.fetch trunk/src:refs/remotes/origin/master'),
None),
0)),
((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'),
((['git', 'config',
'branch.working.git-cl-similarity'],), CERR1),
((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'),
((['git', 'config', '--bool',
'branch.working.git-find-copies'],), CERR1),
((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'),
((['git',
'config', 'branch.working.rietveldissue'],), '12345'),
((['git',
'config', 'rietveld.server'],), 'codereview.example.com'),
((['git',
'config', 'branch.working.merge'],), 'refs/heads/master'),
((['git', 'config', 'branch.working.remote'],), 'origin'),
((['git', 'config', 'branch.working.merge'],),
'refs/heads/master'),
((['git', 'config', 'branch.working.remote'],), 'origin'),
((['git', 'rev-list', '--merges',
'--grep=^SVN changes up to revision [0-9]*$',
'refs/remotes/origin/master^!'],), ''),
((['git', 'rev-list', '^refs/heads/working',
'refs/remotes/origin/master'],),
''),
((['git',
'log', '--grep=^git-svn-id:', '-1', '--pretty=format:%H'],),
'3fc18b62c4966193eb435baabe2d18a3810ec82e'),
((['git',
'rev-list', '^3fc18b62c4966193eb435baabe2d18a3810ec82e',
'refs/remotes/origin/master'],), ''),
((['git',
'merge-base', 'refs/remotes/origin/master', 'HEAD'],),
'fake_ancestor_sha'),
]
@classmethod
def _dcommit_calls_normal(cls):
return [
((['git', 'rev-parse', '--show-cdup'],), ''),
((['git', 'rev-parse', 'HEAD'],),
'00ff397798ea57439712ed7e04ab96e13969ef40'),
((['git',
'diff', '--name-status', '--no-renames', '-r', 'fake_ancestor_sha...',
'.'],),
'M\tPRESUBMIT.py'),
((['git',
'config', 'branch.working.rietveldpatchset'],), '31137'),
((['git', 'config', 'branch.working.rietveldserver'],),
'codereview.example.com'),
((['git', 'config', 'user.email'],), 'author@example.com'),
((['git', 'config', 'rietveld.tree-status-url'],), ''),
]
@classmethod
def _dcommit_calls_bypassed(cls):
return [
((['git', 'config', 'branch.working.rietveldserver'],),
'codereview.example.com'),
]
@classmethod
def _dcommit_calls_3(cls):
return [
((['git',
'diff', '--no-ext-diff', '--stat', '-l100000', '-C50',
'fake_ancestor_sha', 'refs/heads/working'],),
(' PRESUBMIT.py | 2 +-\n'
' 1 files changed, 1 insertions(+), 1 deletions(-)\n')),
((['git', 'show-ref', '--quiet', '--verify',
'refs/heads/git-cl-commit'],), ''),
((['git', 'branch', '-D', 'git-cl-commit'],), ''),
((['git', 'show-ref', '--quiet', '--verify',
'refs/heads/git-cl-cherry-pick'],), CERR1),
((['git', 'rev-parse', '--show-cdup'],), '\n'),
((['git', 'checkout', '-q', '-b', 'git-cl-commit'],), ''),
((['git', 'reset', '--soft', 'fake_ancestor_sha'],), ''),
((['git', 'commit', '-m',
'Issue: 12345\n\nR=john@chromium.org\n\n'
'Review-Url: https://codereview.example.com/12345 .'],),
''),
((['git', 'config', 'rietveld.force-https-commit-url'],), ''),
((['git',
'svn', 'dcommit', '-C50', '--no-rebase', '--rmdir'],),
(('', None), 0)),
((['git', 'checkout', '-q', 'working'],), ''),
((['git', 'branch', '-D', 'git-cl-commit'],), ''),
]
@staticmethod
def _cmd_line(description, args, similarity, find_copies, private, cc):
"""Returns the upload command line passed to upload.RealMain()."""
@ -952,23 +847,6 @@ class TestGitCl(TestCase):
'desc\n\nBUG=500658\nBUG=proj:1234',
[])
def test_dcommit(self):
self.mock(git_cl.sys, 'stdout', StringIO.StringIO())
self.calls = (
self._dcommit_calls_1() +
self._git_sanity_checks('fake_ancestor_sha', 'working') +
self._dcommit_calls_normal() +
self._dcommit_calls_3())
git_cl.main(['dcommit'])
def test_dcommit_bypass_hooks(self):
self.mock(git_cl.sys, 'stdout', StringIO.StringIO())
self.calls = (
self._dcommit_calls_1() +
self._dcommit_calls_bypassed() +
self._dcommit_calls_3())
git_cl.main(['dcommit', '--bypass-hooks'])
def _land_rietveld_common(self, debug=False):
if debug:
# Very useful due to finally clause in git cl land raising exceptions and
@ -984,10 +862,6 @@ class TestGitCl(TestCase):
self.mock(RietveldMock, 'add_comment', staticmethod(
lambda i, c: self._mocked_call(['add_comment', i, c])))
self.calls = [
((['git', 'config', 'rietveld.autoupdate'],), ''),
((['git', 'config', 'rietveld.pending-ref-prefix'],), CERR1),
((['git', 'config', '--local', '--get-regexp', '^svn-remote\\.'],),
CERR1),
((['git', 'symbolic-ref', 'HEAD'],), 'feature'),
((['git', 'config', 'branch.feature.git-cl-similarity'],), CERR1),
((['git', 'symbolic-ref', 'HEAD'],), 'feature'),
@ -995,15 +869,13 @@ class TestGitCl(TestCase):
CERR1),
((['git', 'symbolic-ref', 'HEAD'],), 'feature'),
((['git', 'config', 'branch.feature.rietveldissue'],), '123'),
((['git', 'config', 'rietveld.autoupdate'],), ''),
((['git', 'config', 'rietveld.server'],),
'https://codereview.chromium.org'),
((['git', 'config', 'branch.feature.merge'],), 'refs/heads/master'),
((['git', 'config', 'branch.feature.remote'],), 'origin'),
((['git', 'config', 'branch.feature.merge'],), 'refs/heads/master'),
((['git', 'config', 'branch.feature.remote'],), 'origin'),
((['git', 'rev-list', '--merges',
'--grep=^SVN changes up to revision [0-9]*$',
'refs/remotes/origin/master^!'],), ''),
((['git', 'rev-list', '^feature', 'refs/remotes/origin/master'],),
''), # No commits to rebase, according to local view of origin.
((['git', 'merge-base', 'refs/remotes/origin/master', 'HEAD'],),

@ -4,32 +4,32 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Tests the "preupload and predcommit hooks" functionality, which lets you run
# Tests the "preupload and preland hooks" functionality, which lets you run
# hooks by installing a script into .git/hooks/pre-cl-* first.
set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
setup_hooks() {
upload_retval=$1
dcommit_retval=$2
land_retval=$2
echo > PRESUBMIT.py <<END
def CheckChangeOnUpload(input_api, output_api):
return $upload_retval
def CheckChangeOnCommit(input_api, output_api):
return $dcommit_retval
return $land_retval
END
}
(
set -e
cd git-svn
cd git_checkout
# We need a server set up, but we don't use it. git config rietveld.server localhost:1
@ -42,8 +42,8 @@ END
# Verify git cl upload fails.
test_expect_failure "git-cl upload hook fails" "$GIT_CL upload master"
# Verify git cl dcommit fails.
test_expect_failure "git-cl dcommit hook fails" "$GIT_CL dcommit master"
# Verify git cl land fails.
test_expect_failure "git-cl land hook fails" "$GIT_CL land master"
)
SUCCESS=$?

@ -8,13 +8,12 @@ set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
(
set -e
cd git-svn
cd git_checkout
git config rietveld.server localhost:10000
export GIT_EDITOR=$(which true)
@ -32,14 +31,8 @@ END
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl status has a suggested reviewer" \
"$GIT_CL_STATUS | grep -q 'R=ben@chromium.org'"
test_expect_failure "git-cl dcommit fails w/ missing LGTM" \
"$GIT_CL dcommit -f --no-oauth2"
test_expect_success "git-cl dcommit --tbr succeeds" \
"$GIT_CL dcommit --tbr -f --no-oauth2 | grep -q -- '--tbr was specified'"
test_expect_failure "git-cl land fails w/ missing LGTM" \
"$GIT_CL land -f --no-oauth2"
)
SUCCESS=$?

@ -8,12 +8,12 @@ set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
(
set -e
cd git-svn
cd git_checkout
git checkout -q -b work
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"

@ -8,29 +8,29 @@ set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
(
set -e
cd git-svn
cd git_checkout
cat > .git/hooks/post-cl-dcommit << _EOF
cat > .git/hooks/post-cl-land << _EOF
#!/usr/bin/env bash
git branch -m COMMITTED
_EOF
chmod +x .git/hooks/post-cl-dcommit
chmod +x .git/hooks/post-cl-land
git config rietveld.server localhost:1
git checkout -q --track -b work
git checkout -q -t origin/master -b work
echo "some work done" >> test
git add test; git commit -q -m "work \
TBR=foo"
test_expect_success "dcommitted code" \
"$GIT_CL dcommit --no-oauth2 -f --bypass-hooks -m 'dcommit'"
test_expect_success "landed code" \
"$GIT_CL land --no-oauth2 -f --bypass-hooks -m 'land'"
test_expect_success "post-cl-dcommit hook executed" \
test_expect_success "post-cl-land hook executed" \
"git symbolic-ref HEAD | grep -q COMMITTED"
)
SUCCESS=$?

@ -1,70 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_initgit
setup_gitgit
(
set -e
cd git-git
git checkout -q --track -b work origin
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
echo "some other work done on a branch" >> test
git add test; git commit -q -m "branch work"
test_expect_success "git-cl upload wants a server" \
"$GIT_CL upload --no-oauth2 2>&1 | grep -q 'You must configure'"
git config rietveld.server localhost:10000
# echo $($GIT_CL_STATUS)
test_expect_success "git-cl status has no issue" \
"$GIT_CL_STATUS | grep -q 'No issue assigned'"
# Prevent the editor from coming up when you upload.
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl status now knows the issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
# Push a description to this URL.
URL=$($GIT_CL_STATUS | sed -ne '/Issue number/s/[^(]*(\(.*\))/\1/p')
curl --cookie dev_appserver_login="test@example.com:False" \
--data-urlencode subject="test" \
--data-urlencode description="foo-quux" \
--data-urlencode xsrf_token="$(print_xsrf_token)" \
$URL/edit
test_expect_success "git-cl land ok" \
"$GIT_CL land -f --no-oauth2"
test_expect_success "branch still has an issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
git checkout -q master > /dev/null 2>&1
git pull -q > /dev/null 2>&1
test_expect_success "committed code has proper description" \
"git show | grep -q 'foo-quux'"
cd $GITREPO_PATH
test_expect_success "upstream repo has our commit" \
"git log master 2>/dev/null | grep -q 'foo-quux'"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi

@ -8,13 +8,13 @@ set -e
. ./test-lib.sh
setup_initgit
setup_gitgit
setup_git_remote
setup_git_checkout
(
set -e
cd git-git
git checkout -q --track -b work origin
cd git_checkout
git checkout -q -t origin/master -b work
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
echo "some other work done on a branch" >> test
@ -26,12 +26,12 @@ setup_gitgit
git config rietveld.server localhost:10000
test_expect_success "git-cl status has no issue" \
"$GIT_CL_STATUS | grep -q 'no issue'"
"$GIT_CL_STATUS | grep -q 'No issue assigned'"
# Prevent the editor from coming up when you upload.
export EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | \
"$GIT_CL upload --no-oauth2 -t test master | \
grep -q 'Issue created'"
test_expect_success "git-cl status now knows the issue" \
@ -40,27 +40,28 @@ setup_gitgit
# Check to see if the description contains the local commit messages.
# Should contain 'branch work' x 2.
test_expect_success "git-cl status has the right description for the log" \
"$GIT_CL_STATUS --field desc | [ $( egrep -q '^branch work$' -c ) -eq 2 ]
"[ $($GIT_CL_STATUS --field desc | egrep '^branch work$' -c) -eq 2 ]"
test_expect_success "git-cl status has the right subject from message" \
"$GIT_CL_STATUS --field desc | \
[ $( egrep -q '^test$' --byte-offset) | grep '^0:' ]
"$GIT_CL_STATUS --field desc | head -n 1 | grep -q '^test$'"
test_expect_success "git-cl push ok" \
"$GIT_CL push -f --no-oauth2"
test_expect_success "git-cl land ok" \
"$GIT_CL land --bypass-hooks"
git checkout -q master > /dev/null 2>&1
git pull -q > /dev/null 2>&1
git fetch origin
git checkout origin/master
test_expect_success "committed code has proper summary" \
"[ $(git log -n 1 --pretty=format:%s | egrep '^test$' -c) -eq 1 ]"
test_expect_success "committed code has proper description" \
"git show | [ $( egrep -q '^branch work$' -c ) -eq 2 ]
"[ $(git log -n 1 --pretty=format:%b | egrep '^branch work$' -c) -eq 2 ]"
test_expect_success "issue no longer has a branch" \
"$GIT_CL_STATUS | grep -q 'work : None'"
# # Have to sleep to let the server return the new status.
# sleep 5
# test_expect_success "branch issue is closed" \
# "$GIT_CL_STATUS | grep -q 'work :.*closed'"
cd $GITREPO_PATH
test_expect_success "upstream repo has our commit" \
"git log master 2>/dev/null | [ $( egrep -q '^branch work$' -c ) -eq 2 ]
)
SUCCESS=$?

@ -1,40 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Renaming a file should show up as a rename in the review.
set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
(
set -e
cd git-svn
git config rietveld.server localhost:10000
# Create a branch, rename a file, upload it.
git checkout -q -b rename
git mv test test2
git commit -q -m "renamed"
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
# Look at the uploaded patch and verify it is a rename patch.
echo "Rename test not fully implemented yet. :("
exit 1
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi

@ -17,12 +17,12 @@ if [ -e "$BACKUP_FILE" ]; then
mv "$BACKUP_FILE" "$BACKUP_FILE_TMP"
fi
setup_initgit
setup_gitgit
setup_git_remote
setup_git_checkout
(
set -e
cd git-git
cd git_checkout
DESC="this is the description"

@ -12,12 +12,12 @@ set -e
. ./test-lib.sh
setup_initsvn
setup_gitsvn
setup_git_remote
setup_git_checkout
(
set -e
cd git-svn
cd git_checkout
git config rietveld.server localhost:10000
# Create a branch and give it an issue.
@ -29,8 +29,8 @@ setup_gitsvn
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl dcommits ok" \
"$GIT_CL dcommit -f --no-oauth2"
test_expect_success "git-cl lands ok" \
"$GIT_CL land -f --no-oauth2"
)
SUCCESS=$?

@ -1,60 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
SCRIPT_DIR=$(cd $(dirname "$BASH_SOURCE") && pwd)
cd ${SCRIPT_DIR}
. ./test-lib.sh
setup_initsvn
setup_gitsvn_submodule
(
set -e
prev_svn_revision=`svn info file://$PWD/svnrepo | grep ^Revision | \
sed s/^.*:// | xargs`
cd git-svn-submodule
git config rietveld.server localhost:1
git checkout -q --track -b work
echo "some work done" >> test
git add test; git commit -q -m "work \
TBR=foo"
git_diff=`git diff HEAD^ | sed -n '/^@@/,$p' | xargs`
test_expect_success "dcommitted code" \
"$GIT_CL dcommit --no-oauth2 -f --bypass-hooks -m 'dcommit'"
cd ..
next_svn_revision=`svn info file://$PWD/svnrepo | grep ^Revision | \
sed s/^.*:// | xargs`
test_expect_success "svn got new revision" \
"test $next_svn_revision = `expr $prev_svn_revision + 1`"
svn_diff=`svn diff -c $next_svn_revision file://$PWD/svnrepo | \
sed -n '/^@@/,$p' | xargs`
test_expect_success "svn diff is correct" \
"test \"$git_diff\" = \"$svn_diff\""
cd git-svn-submodule
git svn fetch
last_svn_rev=`git show refs/remotes/origin/trunk | grep git-svn-id: | \
grep -o trunk@[0-9]* | xargs`
test_expect_success "git svn fetch gets new svn revision" \
"test $last_svn_rev = trunk@$next_svn_revision"
)
SUCCESS=$?
#cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi

@ -11,90 +11,20 @@ export DEPOT_TOOLS_UPDATE=0
export PYTHONUNBUFFERED=
PWD=$(pwd)
REPO_URL=file://$PWD/svnrepo
TRUNK_URL=$REPO_URL/trunk
BRANCH_URL=$REPO_URL/branches/some_branch
GITREPO_PATH=$PWD/gitrepo
GITREPO_PATH=$PWD/git_remote
GITREPO_URL=file://$GITREPO_PATH
PATH="$(dirname $PWD):$PATH"
GIT_CL=$(dirname $PWD)/git-cl
GIT_CL_STATUS="$GIT_CL status -f"
# Set up an SVN repo that has a few commits to trunk.
setup_initsvn() {
echo "Setting up test SVN repo..."
rm -rf svnrepo
svnadmin create svnrepo
# Need this in order for Mac SnowLeopard to work
echo "enable-rep-sharing = false" >> svnrepo/db/fsfs.conf
svn mkdir -q -m 'creating trunk' --parents $TRUNK_URL
rm -rf svn
svn co -q $TRUNK_URL svn
(
cd svn
echo "test" > test
svn add -q test
svn commit -q -m "initial commit"
echo "test2" >> test
svn commit -q -m "second commit"
)
svn cp -q -m 'branching' --parents $TRUNK_URL $BRANCH_URL
}
# Set up a git-svn checkout of the repo.
setup_gitsvn() {
echo "Setting up test git-svn repo..."
rm -rf git-svn
# There appears to be no way to make git-svn completely shut up, so we
# redirect its output.
# clone with --prefix origin/ to ensure the same behaviour with old and new
# versions of git (The default prefix was "" prior to Git 2.0)
git svn --prefix origin/ -q clone -s $REPO_URL git-svn >/dev/null 2>&1
(
cd git-svn
git remote add origin https://example.com/fake_refspec
git config user.name 'TestDood'
git config user.email 'TestDood@example.com'
)
}
# Set up a git-svn checkout of the repo and apply merge commits
# (like the submodule repo layout).
setup_gitsvn_submodule() {
echo "Setting up test remote git-svn-submodule repo..."
rm -rf git-svn-submodule
# clone with --prefix origin/ to ensure the same behaviour with old and new
# versions of git (The default prefix was "" prior to Git 2.0)
git svn --prefix origin/ -q clone -s $REPO_URL git-svn-submodule >/dev/null 2>&1
svn_revision=`svn info file://$PWD/svnrepo | grep ^Revision | \
sed s/^.*:// | xargs`
(
cd git-svn-submodule
git config user.name 'TestDood'
git config user.email 'TestDood@example.com'
echo 'merge-file line 1' > merge-file
git add merge-file; git commit -q -m 'First non-svn commit on master'
git checkout -q refs/remotes/origin/trunk
git merge -q --no-commit --no-ff refs/heads/master >/dev/null 2>&1
echo 'merge-edit-file line 1' > merge-edit-file
git add merge-edit-file
git commit -q -m "SVN changes up to revision $svn_revision"
git update-ref refs/heads/master HEAD
git checkout master
)
}
# Set up a git repo that has a few commits to master.
setup_initgit() {
setup_git_remote() {
echo "Setting up test upstream git repo..."
rm -rf gitrepo
mkdir gitrepo
rm -rf git_remote
mkdir git_remote
(
cd gitrepo
cd git_remote
git init -q
git config user.name 'TestDood'
git config user.email 'TestDood@example.com'
@ -110,19 +40,19 @@ setup_initgit() {
}
# Set up a git checkout of the repo.
setup_gitgit() {
setup_git_checkout() {
echo "Setting up test git repo..."
rm -rf git-git
git clone -q $GITREPO_URL git-git
rm -rf git_checkout
git clone -q $GITREPO_URL git_checkout
(
cd git-git
cd git_checkout
git config user.name 'TestDood'
git config user.email 'TestDood@example.com'
)
}
cleanup() {
rm -rf gitrepo svnrepo svn git-git git-svn git-svn-submodule
rm -rf git_remote git_checkout
}
# Usage: test_expect_success "description of test" "test code".

@ -8,12 +8,12 @@ set -e
. ./test-lib.sh
setup_initgit
setup_gitgit
setup_git_remote
setup_git_checkout
(
set -e
cd git-git
cd git_checkout
git checkout -q -b work HEAD^
git checkout -q -t -b work2 work
echo "some work done on a branch that tracks a local branch" >> test

@ -8,12 +8,12 @@ set -e
. ./test-lib.sh
setup_initgit
setup_gitgit
setup_git_remote
setup_git_checkout
(
set -e
cd git-git
cd git_checkout
git checkout -q -b work HEAD^
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"

Loading…
Cancel
Save