No title Revision 646465363833 (Fri Aug 26 2011 at 08:22) - Diff Link to this snippet: https://friendpaste.com/13B0LEy9ZQAGOybTWJzJJQ Embed: manni perldoc borland colorful default murphy trac fruity autumn bw emacs pastie friendly Show line numbers Wrap lines 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237#!/usr/bin/env python# Licensed to the Apache Software Foundation (ASF) under one or more# contributor license agreements. See the NOTICE file distributed with# this work for additional information regarding copyright ownership.# The ASF licenses this file to you under the Apache License, Version 2.0# (the "License"); you may not use this file except in compliance with# the License. You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.import optparse as opimport osimport reimport subprocess as spimport sysimport tempfileimport textwrapimport urlparse__usage__ = "%prog [OPTIONS] SVN_PATH GIT_DIR"SVN_BASE = "https://svn.apache.org/repos/asf/"REF_RE = re.compile("refs/remotes/([^@]+)")def options(): return [ op.make_option('-a', '--authors', metavar="FILE", dest="authors", default="/usr/local/etc/asf-authors", help="Path to the ASF authors file."), op.make_option('-d', '--description', metavar="DESC", dest='desc', help="A short project description. ie, 'Apache Jackrabbit'") ]def main(): parser = op.OptionParser(usage=__usage__, option_list=options()) opts, args = parser.parse_args() if len(args) == 0: parser.error("Missing required SVN_URL and GIT_DIR arguments.") if len(args) == 1: parser.error("Missing required GIT_DIR argument.") if len(args) > 2: parser.error("Unknown arguments: %s" % ", ".join(args[2:])) svn_url = urlparse.urljoin(SVN_BASE, args[0].lstrip().lstrip("/")) git_dir = args[1] os.putenv("GIT_DIR", git_dir) if opts.authors is None: opts.authors = "/usr/local/etc/asf-authors" if os.path.exists(git_dir): error("Git directory exists: %s" % git_dir) if not os.path.exists(opts.authors): error("Missing authors file: %s" % opts.authors) init_git_dir(git_dir, svn_url, opts.desc) clone_svn(git_dir, opts.authors) cleanup_clone() configure_asfgit(git_dir)def init_git_dir(git_dir, svn_url, desc): log("Creating mirror in: %s" % git_dir) git("svn", "init", "-s", svn_url) git("config", "gitweb.owner", "The Apache Software Foundation") save(os.path.join(git_dir, "HEAD"), "ref: refs/heads/trunk") git("update-server-info") if desc is None: desc = run_editor(initial="Project description, ie 'Apache Jackrabbit'") if desc is None: error("No repository description provided.") save(os.path.join(git_dir, "description"), desc)def clone_svn(git_dir, authors): log("Initializing Git repository.") git("svn", "fetch", "--authors-file", authors, "--log-window-size=10000") log("Updating branch refs.") refs = git("for-each-ref", "refs/remotes", capture=True) for ref in refs.splitlines(): match = REF_RE.match(ref.split()[-1]) if not match: continue ref = match.group(1) if ref.startswith("tags/"): continue git("update-ref", "refs/heads/%s" % ref, "refs/remotes/%s" % ref) log("Creating Git tags from SVN pseudo-tags") refs = git("for-each-ref", "refs/remotes/tags", capture=True) for ref in refs.splitlines(): ref = ref.split()[-1] if ref.find("@") >= 0: continue tag = ref.split("/", 3)[-1] for opt in ("name", "email", "date"): fmt = "--format=%%(committer%s)" % opt val = git("for-each-ref", fmt, ref, capture=True).strip() os.putenv("GIT_COMMITTER_%s" % opt.upper(), val) git("tag", "-f", "-m", tag, tag, ref)def cleanup_clone(): log("Cleaning up new Git clone.") git("update-server-info") git("gc", "--aggressive")def configure_asfgit(git_dir): asfgit = os.getenv("ASFGIT_ADMIN") or "/usr/local/etc/asfgit-admin" if not os.path.exists(asfgit): log("WARNING: asfgit-admin directory not found.") log("WARNING: Skipping hosting configuration.") return log("Installing hook symlinks.") for name in ("pre-receive", "post-receive"): src = os.path.abspath(os.path.join(asfgit, "hooks", name)) dst = os.path.join(git_dir, "hooks", name) if not os.path.exists(src): error("Missing pre-receive hook: %s" % name) if os.path.exists(dst): os.unlink(dst) os.symlink(src, dst) log("Initializaing hosting configuration") cfgfile = os.path.join(asfgit, "conf", "gitconfig") dstfile = os.path.join(git_dir, "config") # Make sure it hasn't already been initialized try: sp.check_output(["git", "config", "hooks.asfgit.debug"]) added = True except sp.CalledProcessError: added = False if not added: # Get base config if not os.path.exists(cfgfile): error("Missing default git configuration: %s" % cfgfile) with open(cfgfile) as handle: config = handle.read() git_repo = os.path.basename(git_dir) config = config % {"git_repo": git_repo} # Append the config data to the git config # and let the user review it. if not os.path.exists(dstfile): error("Missing destinationg git config: %s" % dstfile) with open(dstfile, "a") as handle: handle.write(config) # Boot the user's editor to review the conifg. run_editor(filename=dstfile) # Final steps git_repo = os.path.basename(git_dir) log(textwrap.dedent("""\ To finish the hosting configuration you need to copy %(git_repo)s to the repository hosting directory and run the following: $ sudo chown -R nobody:daemon $(REPOS)/%(git_repo)s $ sudo chmod g+x $(REPOS)/%(git_repo)s At the time of this writing, $(REPOS) should be: /usr/local/www/git-wip-us.apache.org/repos/asf """ % {"git_repo": git_repo})) def run_editor(filename=None, initial=""): editor = os.getenv("EDITOR", "nano") if filename is None: with tempfile.NamedTemporaryFile(delete=False) as tf: fname = tf.name tf.write(initial) else: fname = filename try: if sp.call([editor, fname]) != 0: return None with open(fname) as handle: return handle.read() finally: if filename is None: os.remove(fname)def git(cmd, *args, **kwargs): cmd = ["git", cmd] + list(args) if kwargs.pop("capture", False): return run(cmd, stderr=sp.STDOUT) sp.check_call(cmd)def run(cmd, *args, **kwargs): if isinstance(cmd, list): return sp.check_output(cmd, **kwargs) else: return sp.check_output([cmd] + list(args), **kwargs)def save(fname, contents): with open(fname, "w") as handle: handle.write(contents)def log(mesg): sys.stderr.write("%s\n" % mesg)def error(mesg, exit_code=1): sys.stderr.write("ERROR: %s\n" % mesg) sys.exit(exit_code)if __name__ == '__main__': main()