Merge branch 'sr/remote-helper-export'

* sr/remote-helper-export:
  t5800: testgit helper requires Python support
  Makefile: Simplify handling of python scripts
  remote-helpers: add tests for testgit helper
  remote-helpers: add testgit helper
  remote-helpers: add support for an export command
  remote-helpers: allow requesing the path to the .git directory
  fast-import: always create marks_file directories
  clone: also configure url for bare clones
  clone: pass the remote name to remote_get

Conflicts:
	Makefile
This commit is contained in:
Junio C Hamano
2010-05-21 04:02:15 -07:00
11 changed files with 671 additions and 27 deletions

View File

@ -0,0 +1,51 @@
import os
import subprocess
import sys
class GitExporter(object):
"""An exporter for testgit repositories.
The exporter simply delegates to git fast-export.
"""
def __init__(self, repo):
"""Creates a new exporter for the specified repo.
"""
self.repo = repo
def export_repo(self, base):
"""Exports a fast-export stream for the given directory.
Simply delegates to git fast-epxort and pipes it through sed
to make the refs show up under the prefix rather than the
default refs/heads. This is to demonstrate how the export
data can be stored under it's own ref (using the refspec
capability).
"""
dirname = self.repo.get_base_path(base)
path = os.path.abspath(os.path.join(dirname, 'testgit.marks'))
if not os.path.exists(dirname):
os.makedirs(dirname)
print "feature relative-marks"
if os.path.exists(os.path.join(dirname, 'git.marks')):
print "feature import-marks=%s/git.marks" % self.repo.hash
print "feature export-marks=%s/git.marks" % self.repo.hash
sys.stdout.flush()
args = ["git", "--git-dir=" + self.repo.gitpath, "fast-export", "--export-marks=" + path]
if os.path.exists(path):
args.append("--import-marks=" + path)
args.append("HEAD")
p1 = subprocess.Popen(args, stdout=subprocess.PIPE)
args = ["sed", "s_refs/heads/_" + self.repo.prefix + "_g"]
subprocess.check_call(args, stdin=p1.stdout)

View File

@ -0,0 +1,38 @@
import os
import subprocess
class GitImporter(object):
"""An importer for testgit repositories.
This importer simply delegates to git fast-import.
"""
def __init__(self, repo):
"""Creates a new importer for the specified repo.
"""
self.repo = repo
def do_import(self, base):
"""Imports a fast-import stream to the given directory.
Simply delegates to git fast-import.
"""
dirname = self.repo.get_base_path(base)
if self.repo.local:
gitdir = self.repo.gitpath
else:
gitdir = os.path.abspath(os.path.join(dirname, '.git'))
path = os.path.abspath(os.path.join(dirname, 'git.marks'))
if not os.path.exists(dirname):
os.makedirs(dirname)
args = ["git", "--git-dir=" + gitdir, "fast-import", "--quiet", "--export-marks=" + path]
if os.path.exists(path):
args.append("--import-marks=" + path)
subprocess.check_call(args)

View File

@ -0,0 +1,61 @@
import os
import subprocess
from git_remote_helpers.util import die, warn
class NonLocalGit(object):
"""Handler to interact with non-local repos.
"""
def __init__(self, repo):
"""Creates a new non-local handler for the specified repo.
"""
self.repo = repo
def clone(self, base):
"""Clones the non-local repo to base.
Does nothing if a clone already exists.
"""
path = os.path.join(self.repo.get_base_path(base), '.git')
# already cloned
if os.path.exists(path):
return path
os.makedirs(path)
args = ["git", "clone", "--bare", "--quiet", self.repo.gitpath, path]
subprocess.check_call(args)
return path
def update(self, base):
"""Updates checkout of the non-local repo in base.
"""
path = os.path.join(self.repo.get_base_path(base), '.git')
if not os.path.exists(path):
die("could not find repo at %s", path)
args = ["git", "--git-dir=" + path, "fetch", "--quiet", self.repo.gitpath]
subprocess.check_call(args)
args = ["git", "--git-dir=" + path, "update-ref", "refs/heads/master", "FETCH_HEAD"]
subprocess.check_call(args)
def push(self, base):
"""Pushes from the non-local repo to base.
"""
path = os.path.join(self.repo.get_base_path(base), '.git')
if not os.path.exists(path):
die("could not find repo at %s", path)
args = ["git", "--git-dir=" + path, "push", "--quiet", self.repo.gitpath]
subprocess.check_call(args)

View File

@ -0,0 +1,70 @@
import os
import subprocess
def sanitize(rev, sep='\t'):
"""Converts a for-each-ref line to a name/value pair.
"""
splitrev = rev.split(sep)
branchval = splitrev[0]
branchname = splitrev[1].strip()
if branchname.startswith("refs/heads/"):
branchname = branchname[11:]
return branchname, branchval
def is_remote(url):
"""Checks whether the specified value is a remote url.
"""
prefixes = ["http", "file", "git"]
return any(url.startswith(i) for i in prefixes)
class GitRepo(object):
"""Repo object representing a repo.
"""
def __init__(self, path):
"""Initializes a new repo at the given path.
"""
self.path = path
self.head = None
self.revmap = {}
self.local = not is_remote(self.path)
if(self.path.endswith('.git')):
self.gitpath = self.path
else:
self.gitpath = os.path.join(self.path, '.git')
if self.local and not os.path.exists(self.gitpath):
os.makedirs(self.gitpath)
def get_revs(self):
"""Fetches all revs from the remote.
"""
args = ["git", "ls-remote", self.gitpath]
path = ".cached_revs"
ofile = open(path, "w")
subprocess.check_call(args, stdout=ofile)
output = open(path).readlines()
self.revmap = dict(sanitize(i) for i in output)
if "HEAD" in self.revmap:
del self.revmap["HEAD"]
self.revs = self.revmap.keys()
ofile.close()
def get_head(self):
"""Determines the head of a local repo.
"""
if not self.local:
return
path = os.path.join(self.gitpath, "HEAD")
head = open(path).readline()
self.head, _ = sanitize(head, ' ')