提交 2fe40b63 编写于 作者: S Sverre Rabbelier 提交者: Junio C Hamano

Add Python support library for remote helpers

This patch introduces parts of a Python package called
"git_remote_helpers" containing the building blocks for
remote helpers written in Python.

No actual remote helpers are part of this patch, this patch only
includes the common basics needed to start writing such helpers.

The patch includes the necessary Makefile additions to build and
install the git_remote_helpers Python package along with the rest of
Git.

This patch is based on Johan Herland's git_remote_cvs patch and
has been improved by the following contributions:
- David Aguilar: Lots of Python coding style fixes
- David Aguilar: DESTDIR support in Makefile

Cc: David Aguilar <davvid@gmail.com>
Cc: Johan Herland <johan@herland.net>
Signed-off-by: NSverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: NJohan Herland <johan@herland.net>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 d4e1b47a
......@@ -1398,6 +1398,9 @@ ifndef NO_TCLTK
endif
ifndef NO_PERL
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
endif
ifndef NO_PYTHON
$(QUIET_SUBDIR0)git_remote_helpers $(QUIET_SUBDIR1) PYTHON_PATH='$(PYTHON_PATH_SQ)' prefix='$(prefix_SQ)' all
endif
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
......@@ -1517,6 +1520,35 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
mv $@+ $@
endif # NO_PERL
ifndef NO_PYTHON
$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS
$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py
$(QUIET_GEN)$(RM) $@ $@+ && \
INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
--no-print-directory prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' \
instlibdir` && \
sed -e '1{' \
-e ' s|#!.*python|#!$(PYTHON_PATH_SQ)|' \
-e '}' \
-e 's|^import sys.*|&; \\\
import os; \\\
sys.path[0] = os.environ.has_key("GITPYTHONLIB") and \\\
os.environ["GITPYTHONLIB"] or \\\
"@@INSTLIBDIR@@"|' \
-e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
$@.py >$@+ && \
chmod +x $@+ && \
mv $@+ $@
else # NO_PYTHON
$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : unimplemented.sh
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@@REASON@@|NO_PYTHON=$(NO_PYTHON)|g' \
unimplemented.sh >$@+ && \
chmod +x $@+ && \
mv $@+ $@
endif # NO_PYTHON
configure: configure.ac
$(QUIET_GEN)$(RM) $@ $<+ && \
sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
......@@ -1741,6 +1773,9 @@ install: all
ifndef NO_PERL
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
endif
ifndef NO_PYTHON
$(MAKE) -C git_remote_helpers prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
endif
ifndef NO_TCLTK
$(MAKE) -C gitk-git install
$(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install
......@@ -1854,6 +1889,9 @@ clean:
ifndef NO_PERL
$(RM) gitweb/gitweb.cgi
$(MAKE) -C perl clean
endif
ifndef NO_PYTHON
$(MAKE) -C git_remote_helpers clean
endif
$(MAKE) -C templates/ clean
$(MAKE) -C t/ clean
......
#
# Makefile for the git_remote_helpers python support modules
#
pysetupfile:=setup.py
# Shell quote (do not use $(call) to accommodate ancient setups);
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
ifndef PYTHON_PATH
PYTHON_PATH = /usr/bin/python
endif
ifndef prefix
prefix = $(HOME)
endif
ifndef V
QUIET = @
QUIETSETUP = --quiet
endif
PYLIBDIR=$(shell $(PYTHON_PATH) -c \
"import sys; \
print 'lib/python%i.%i/site-packages' % sys.version_info[:2]")
all: $(pysetupfile)
$(QUIET)$(PYTHON_PATH) $(pysetupfile) $(QUIETSETUP) build
install: $(pysetupfile)
$(PYTHON_PATH) $(pysetupfile) install --prefix $(DESTDIR_SQ)$(prefix)
instlibdir: $(pysetupfile)
@echo "$(DESTDIR_SQ)$(prefix)/$(PYLIBDIR)"
clean:
$(QUIET)$(PYTHON_PATH) $(pysetupfile) $(QUIETSETUP) clean -a
$(RM) *.pyo *.pyc
#!/usr/bin/env python
"""Support library package for git remote helpers.
Git remote helpers are helper commands that interfaces with a non-git
repository to provide automatic import of non-git history into a Git
repository.
This package provides the support library needed by these helpers..
The following modules are included:
- git.git - Interaction with Git repositories
- util - General utility functionality use by the other modules in
this package, and also used directly by the helpers.
"""
此差异已折叠。
#!/usr/bin/env python
"""Distutils build/install script for the git_remote_helpers package."""
from distutils.core import setup
setup(
name = 'git_remote_helpers',
version = '0.1.0',
description = 'Git remote helper program for non-git repositories',
license = 'GPLv2',
author = 'The Git Community',
author_email = 'git@vger.kernel.org',
url = 'http://www.git-scm.com/',
package_dir = {'git_remote_helpers': ''},
packages = ['git_remote_helpers', 'git_remote_helpers.git'],
)
#!/usr/bin/env python
"""Misc. useful functionality used by the rest of this package.
This module provides common functionality used by the other modules in
this package.
"""
import sys
import os
import subprocess
# Whether or not to show debug messages
DEBUG = False
def notify(msg, *args):
"""Print a message to stderr."""
print >> sys.stderr, msg % args
def debug (msg, *args):
"""Print a debug message to stderr when DEBUG is enabled."""
if DEBUG:
print >> sys.stderr, msg % args
def error (msg, *args):
"""Print an error message to stderr."""
print >> sys.stderr, "ERROR:", msg % args
def warn(msg, *args):
"""Print a warning message to stderr."""
print >> sys.stderr, "warning:", msg % args
def die (msg, *args):
"""Print as error message to stderr and exit the program."""
error(msg, *args)
sys.exit(1)
class ProgressIndicator(object):
"""Simple progress indicator.
Displayed as a spinning character by default, but can be customized
by passing custom messages that overrides the spinning character.
"""
States = ("|", "/", "-", "\\")
def __init__ (self, prefix = "", f = sys.stdout):
"""Create a new ProgressIndicator, bound to the given file object."""
self.n = 0 # Simple progress counter
self.f = f # Progress is written to this file object
self.prev_len = 0 # Length of previous msg (to be overwritten)
self.prefix = prefix # Prefix prepended to each progress message
self.prefix_lens = [] # Stack of prefix string lengths
def pushprefix (self, prefix):
"""Append the given prefix onto the prefix stack."""
self.prefix_lens.append(len(self.prefix))
self.prefix += prefix
def popprefix (self):
"""Remove the last prefix from the prefix stack."""
prev_len = self.prefix_lens.pop()
self.prefix = self.prefix[:prev_len]
def __call__ (self, msg = None, lf = False):
"""Indicate progress, possibly with a custom message."""
if msg is None:
msg = self.States[self.n % len(self.States)]
msg = self.prefix + msg
print >> self.f, "\r%-*s" % (self.prev_len, msg),
self.prev_len = len(msg.expandtabs())
if lf:
print >> self.f
self.prev_len = 0
self.n += 1
def finish (self, msg = "done", noprefix = False):
"""Finalize progress indication with the given message."""
if noprefix:
self.prefix = ""
self(msg, True)
def start_command (args, cwd = None, shell = False, add_env = None,
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = subprocess.PIPE):
"""Start the given command, and return a subprocess object.
This provides a simpler interface to the subprocess module.
"""
env = None
if add_env is not None:
env = os.environ.copy()
env.update(add_env)
return subprocess.Popen(args, bufsize = 1, stdin = stdin, stdout = stdout,
stderr = stderr, cwd = cwd, shell = shell,
env = env, universal_newlines = True)
def run_command (args, cwd = None, shell = False, add_env = None,
flag_error = True):
"""Run the given command to completion, and return its results.
This provides a simpler interface to the subprocess module.
The results are formatted as a 3-tuple: (exit_code, output, errors)
If flag_error is enabled, Error messages will be produced if the
subprocess terminated with a non-zero exit code and/or stderr
output.
The other arguments are passed on to start_command().
"""
process = start_command(args, cwd, shell, add_env)
(output, errors) = process.communicate()
exit_code = process.returncode
if flag_error and errors:
error("'%s' returned errors:\n---\n%s---", " ".join(args), errors)
if flag_error and exit_code:
error("'%s' returned exit code %i", " ".join(args), exit_code)
return (exit_code, output, errors)
def file_reader_method (missing_ok = False):
"""Decorator for simplifying reading of files.
If missing_ok is True, a failure to open a file for reading will
not raise the usual IOError, but instead the wrapped method will be
called with f == None. The method must in this case properly
handle f == None.
"""
def _wrap (method):
"""Teach given method to handle both filenames and file objects.
The given method must take a file object as its second argument
(the first argument being 'self', of course). This decorator
will take a filename given as the second argument and promote
it to a file object.
"""
def _wrapped_method (self, filename, *args, **kwargs):
if isinstance(filename, file):
f = filename
else:
try:
f = open(filename, 'r')
except IOError:
if missing_ok:
f = None
else:
raise
try:
return method(self, f, *args, **kwargs)
finally:
if not isinstance(filename, file) and f:
f.close()
return _wrapped_method
return _wrap
def file_writer_method (method):
"""Decorator for simplifying writing of files.
Enables the given method to handle both filenames and file objects.
The given method must take a file object as its second argument
(the first argument being 'self', of course). This decorator will
take a filename given as the second argument and promote it to a
file object.
"""
def _new_method (self, filename, *args, **kwargs):
if isinstance(filename, file):
f = filename
else:
# Make sure the containing directory exists
parent_dir = os.path.dirname(filename)
if not os.path.isdir(parent_dir):
os.makedirs(parent_dir)
f = open(filename, 'w')
try:
return method(self, f, *args, **kwargs)
finally:
if not isinstance(filename, file):
f.close()
return _new_method
......@@ -638,6 +638,15 @@ test -d ../templates/blt || {
error "You haven't built things yet, have you?"
}
if test -z "$GIT_TEST_INSTALLED"
then
GITPYTHONLIB="$(pwd)/../git_remote_helpers/build/lib"
export GITPYTHONLIB
test -d ../git_remote_helpers/build || {
error "You haven't built git_remote_helpers yet, have you?"
}
fi
if ! test -x ../test-chmtime; then
echo >&2 'You need to build test-chmtime:'
echo >&2 'Run "make test-chmtime" in the source (toplevel) directory'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册