Commit d629fb40 authored by agable@chromium.org's avatar agable@chromium.org

Introduct git-auto-svn

This tool can automatically set up the necessary git-svn metadata for our
repos that live in SVN but are mirrored to Chrome.

R=iannucci@chromium.org, tandrii@chromium.org
BUG=418973

Review URL: https://codereview.chromium.org/611253003

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@292241 0039d316-1c4b-4281-b951-d872f2087c98
parent 782570c4
#!/usr/bin/env bash
# Copyright 2014 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.
# git_map_branches.py -- a git-command for presenting a graphical view of git
# branches in the current repo, and their relationships to each other.
. $(type -P python_git_runner.sh)
#!/usr/bin/env python
# Copyright 2014 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.
"""Performs all git-svn setup steps necessary for 'git svn dcommit' to work.
Assumes that trunk of the svn remote maps to master of the git remote.
Example:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools
cd depot_tools
git auto-svn
"""
import argparse
import os
import sys
import urlparse
import subprocess2
from git_common import run as run_git
from git_common import run_stream as run_git_stream
from git_common import set_config, root, ROOT
from git_footers import parse_footers, get_unique, GIT_SVN_ID_PATTERN
SVN_EXE = ROOT+'\\svn.bat' if sys.platform.startswith('win') else 'svn'
def run_svn(*cmd, **kwargs):
"""Runs an svn command.
Returns (stdout, stderr) as a pair of strings.
Raises subprocess2.CalledProcessError on nonzero return code.
"""
kwargs.setdefault('stdin', subprocess2.PIPE)
kwargs.setdefault('stdout', subprocess2.PIPE)
kwargs.setdefault('stderr', subprocess2.PIPE)
cmd = (SVN_EXE,) + cmd
proc = subprocess2.Popen(cmd, **kwargs)
ret, err = proc.communicate()
retcode = proc.wait()
if retcode != 0:
raise subprocess2.CalledProcessError(retcode, cmd, os.getcwd(), ret, err)
return ret, err
def main(argv):
# No command line flags. Just use the parser to prevent people from trying
# to pass flags that don't do anything, and to provide 'usage'.
parser = argparse.ArgumentParser(
description='Automatically set up git-svn for a repo mirrored from svn.')
parser.parse_args(argv[1:])
upstream = root()
message = run_git('log', '-1', '--format=%B', upstream)
footers = parse_footers(message)
git_svn_id = get_unique(footers, 'git-svn-id')
match = GIT_SVN_ID_PATTERN.match(git_svn_id)
assert match, 'No valid git-svn-id footer found on %s.' % upstream
print 'Found git-svn-id footer %s on %s' % (match.group(1), upstream)
parsed_svn = urlparse.urlparse(match.group(1))
path_components = parsed_svn.path.split('/')
svn_repo = None
svn_path = None
for i in xrange(len(path_components)):
try:
maybe_repo = '%s://%s%s' % (
parsed_svn.scheme, parsed_svn.netloc, '/'.join(path_components[:i+1]))
print 'Checking ', maybe_repo
run_svn('info', maybe_repo)
svn_repo = maybe_repo
svn_path = '/'.join(path_components[i+1:])
break
except subprocess2.CalledProcessError:
continue
assert svn_repo is not None, 'Unable to find svn repo for %s' % match.group(1)
print 'Found upstream svn repo %s and path %s' % (svn_repo, svn_path)
prefix = upstream.rsplit('/')[0]
run_git('svn', 'init', '--prefix=%s' % prefix, '-T', svn_path, svn_repo)
set_config('svn-remote.svn.fetch',
'%s:refs/remotes/%s' % (svn_path, upstream))
print 'Configured metadata, running "git svn fetch". This may take some time.'
for line in run_git_stream('svn', 'fetch').xreadlines():
print line.strip()
if __name__ == '__main__':
sys.exit(main(sys.argv))
......@@ -319,15 +319,6 @@ def branches(*args):
yield line.split()[-1]
def run_with_retcode(*cmd, **kwargs):
"""Run a command but only return the status code."""
try:
run(*cmd, **kwargs)
return 0
except subprocess2.CalledProcessError as cpe:
return cpe.returncode
def config(option, default=None):
try:
return run('config', '--get', option) or default
......@@ -551,6 +542,15 @@ def run(*cmd, **kwargs):
return run_with_stderr(*cmd, **kwargs)[0]
def run_with_retcode(*cmd, **kwargs):
"""Run a command but only return the status code."""
try:
run(*cmd, **kwargs)
return 0
except subprocess2.CalledProcessError as cpe:
return cpe.returncode
def run_stream(*cmd, **kwargs):
"""Runs a git command. Returns stdout as a PIPE (file-like object).
......@@ -600,6 +600,7 @@ def set_branch_config(branch, option, value, scope='local'):
def set_config(option, value, scope='local'):
run('config', '--' + scope, option, value)
def squash_current_branch(header=None, merge_base=None):
header = header or 'git squash commit.'
merge_base = merge_base or get_or_create_merge_base(current_branch())
......@@ -723,6 +724,7 @@ def upstream(branch):
except subprocess2.CalledProcessError:
return None
def get_git_version():
"""Returns a tuple that contains the numeric components of the current git
version."""
......
......@@ -11,10 +11,12 @@ from collections import defaultdict
import git_common as git
FOOTER_PATTERN = re.compile(r'^\s*([\w-]+): (.*)$')
CHROME_COMMIT_POSITION_PATTERN = re.compile(r'^([\w/-]+)@{#(\d+)}$')
GIT_SVN_ID_PATTERN = re.compile('^([^\s@]+)@(\d+)')
def normalize_name(header):
return '-'.join([ word.title() for word in header.strip().split('-') ])
......
This diff is collapsed.
'\" t
.\" Title: git-auto-svn
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 09/30/2014
.\" Manual: Chromium depot_tools Manual
.\" Source: depot_tools 2bbacdc
.\" Language: English
.\"
.TH "GIT\-AUTO\-SVN" "1" "09/30/2014" "depot_tools 2bbacdc" "Chromium depot_tools Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
git-auto-svn \- Automatically set up git\-svn metadata for a repo mirrored from SVN\&.
.SH "SYNOPSIS"
.sp
.nf
\fIgit auto\-svn\fR
.fi
.sp
.SH "DESCRIPTION"
.sp
git auto\-svn automatically sets up git\-svn metadata and runs git\-svn fetch for repos that are homed in SVN but mirrored to Git (such as depot_tools itself)\&.
.sp
It determines the metadata to use by inspecting the git\-svn\-id footer of the HEAD of the remote upstream ref (by default, origin/master)\&. git\-svn\-id footers look like this:
.sp
.if n \{\
.RS 4
.\}
.nf
git\-svn\-id: svn://some\&.host\&.org/repo/path/to/a/sub/folder@123456 0039d316\-1c4b\-4281\-b951\-d872f2087c98
.fi
.if n \{\
.RE
.\}
.sp
git auto\-svn extracts the repository url (svn://some\&.host\&.org/repo/path/to/a/sub/folder) from the git\-svn\-id, and splits it into the root repository (svn://some\&.host\&.org/repo) and the path within that repository (/path/to/a/sub/folder)\&.
.sp
It then sets up the following stanza in \&.git/config:
.sp
.if n \{\
.RS 4
.\}
.nf
[svn\-remote "svn"]
url = svn://some\&.host\&.org/repo
fetch = path/to/a/sub/folder:refs/remotes/origin/master
.fi
.if n \{\
.RE
.\}
.sp
Finally, it runs git svn fetch to pull in the data from the svn remote\&.
.SH "CONFIGURATION VARIABLES"
.SS "svn\-remote\&.svn\&.url"
.sp
This is the url of the root of the remote svn repository\&.
.SS "svn\-remote\&.svn\&.fetch"
.sp
This looks like a git refspec, but maps a subdirectory of the svn repository to a single ref in the git remote\&.
.SH "EXAMPLE"
.sp
.if n \{\
.RS 4
.\}
.nf
git clone https://chromium\&.googlesource\&.com/chromium/tools/depot_tools
cd depot_tools
git auto\-svn
.fi
.if n \{\
.RE
.\}
.sp
This results in the following stanza in depot_tools/\&.git/config:
.sp
.if n \{\
.RS 4
.\}
.nf
[svn\-remote "svn"]
url = svn://svn\&.chromium\&.org/chrome
fetch = trunk/tools/depot_tools:refs/remotes/origin/master
.fi
.if n \{\
.RE
.\}
.SH "CHROMIUM DEPOT_TOOLS"
.sp
Part of the chromium \fBdepot_tools\fR(7) suite\&. These tools are meant to assist with the development of chromium and related projects\&. Download the tools from \m[blue]\fBhere\fR\m[]\&\s-2\u[1]\d\s+2\&.
.SH "NOTES"
.IP " 1." 4
here
.RS 4
\%https://chromium.googlesource.com/chromium/tools/depot_tools.git
.RE
Automatically set up git-svn metadata for a repo mirrored from SVN.
git-auto-svn(1)
===============
NAME
----
git-auto-svn -
include::_git-auto-svn_desc.helper.txt[]
SYNOPSIS
--------
[verse]
'git auto-svn'
DESCRIPTION
-----------
`git auto-svn` automatically sets up git-svn metadata and runs git-svn fetch for
repos that are homed in SVN but mirrored to Git (such as depot_tools itself).
It determines the metadata to use by inspecting the `git-svn-id` footer of the
HEAD of the remote upstream ref (by default, `origin/master`). `git-svn-id`
footers look like this:
git-svn-id: svn://some.host.org/repo/path/to/a/sub/folder@123456 0039d316-1c4b-4281-b951-d872f2087c98
`git auto-svn` extracts the repository url
(svn://some.host.org/repo/path/to/a/sub/folder) from the `git-svn-id`, and
splits it into the root repository (svn://some.host.org/repo) and the path
within that repository (/path/to/a/sub/folder).
It then sets up the following stanza in .git/config:
[svn-remote "svn"]
url = svn://some.host.org/repo
fetch = path/to/a/sub/folder:refs/remotes/origin/master
Finally, it runs `git svn fetch` to pull in the data from the svn remote.
CONFIGURATION VARIABLES
-----------------------
svn-remote.svn.url
~~~~~~~~~~~~~~~~~~
This is the url of the root of the remote svn repository.
svn-remote.svn.fetch
~~~~~~~~~~~~~~~~~~~~
This looks like a git refspec, but maps a subdirectory of the svn repository
to a single ref in the git remote.
EXAMPLE
-------
git clone https://chromium.googlesource.com/chromium/tools/depot_tools
cd depot_tools
git auto-svn
This results in the following stanza in `depot_tools/.git/config`:
[svn-remote "svn"]
url = svn://svn.chromium.org/chrome
fetch = trunk/tools/depot_tools:refs/remotes/origin/master
include::_footer.txt[]
// vim: ft=asciidoc:
......@@ -23,6 +23,7 @@ ensure_in_path() {
}
ensure_in_path xmlto
ensure_in_path hg
DFLT_CATALOG_PATH="/usr/local/etc/xml/catalog"
if [[ ! $XML_CATALOG_FILES && -f "$DFLT_CATALOG_PATH" ]]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment