Skip to content

Commit

Permalink
Merge branch 'sr/vcs-helper'
Browse files Browse the repository at this point in the history
* sr/vcs-helper:
  tests: handle NO_PYTHON setting
  builtin-push: don't access freed transport->url
  Add Python support library for remote helpers
  Basic build infrastructure for Python scripts
  Allow helpers to report in "list" command that the ref is unchanged
  Fix various memory leaks in transport-helper.c
  Allow helper to map private ref names into normal names
  Add support for "import" helper command
  Allow specifying the remote helper in the url
  Add a config option for remotes to specify a foreign vcs
  Allow fetch to modify refs
  Use a function to determine whether a remote is valid
  Allow programs to not depend on remotes having urls
  Fix memory leak in helper method for disconnect

Conflicts:
	Documentation/git-remote-helpers.txt
	Makefile
	builtin-ls-remote.c
	builtin-push.c
	transport-helper.c
  • Loading branch information
gitster committed Dec 26, 2009
2 parents 902f235 + ac10a85 commit e74f43f
Show file tree
Hide file tree
Showing 21 changed files with 1,322 additions and 48 deletions.
4 changes: 4 additions & 0 deletions Documentation/config.txt
Expand Up @@ -1461,6 +1461,10 @@ remote.<name>.tagopt::
Setting this value to \--no-tags disables automatic tag following when
fetching from remote <name>

remote.<name>.vcs::
Setting this to a value <vcs> will cause git to interact with
the remote with the git-remote-<vcs> helper.

remotes.<group>::
The list of remotes which are fetched by "git remote update
<group>". See linkgit:git-remote[1].
Expand Down
28 changes: 28 additions & 0 deletions Documentation/git-remote-helpers.txt
Expand Up @@ -79,6 +79,17 @@ style string if it contains an LF.
+
Supported if the helper has the "push" capability.

'import' <name>::
Produces a fast-import stream which imports the current value
of the named ref. It may additionally import other refs as
needed to construct the history efficiently. The script writes
to a helper-specific private namespace. The value of the named
ref should be written to a location in this namespace derived
by applying the refspecs from the "refspec" capability to the
name of the ref.
+
Supported if the helper has the "import" capability.

If a fatal error occurs, the program writes the error message to
stderr and exits. The caller should expect that a suitable error
message has been printed if the child closes the connection without
Expand All @@ -99,6 +110,19 @@ CAPABILITIES
'push'::
This helper supports the 'push' command.

'import'::
This helper supports the 'import' command.

'refspec' 'spec'::
When using the import command, expect the source ref to have
been written to the destination ref. The earliest applicable
refspec takes precedence. For example
"refs/heads/*:refs/svn/origin/branches/*" means that, after an
"import refs/heads/name", the script has written to
refs/svn/origin/branches/name. If this capability is used at
all, it must cover all refs reported by the list command; if
it is not used, it is effectively "*:*"

REF LIST ATTRIBUTES
-------------------

Expand All @@ -107,6 +131,10 @@ REF LIST ATTRIBUTES
commands. A helper might chose to acquire the ref list by
opening a different type of connection to the destination.

'unchanged'::
This ref is unchanged since the last import or fetch, although
the helper cannot necessarily determine what value that produced.

OPTIONS
-------
'option verbosity' <N>::
Expand Down
53 changes: 53 additions & 0 deletions Makefile
Expand Up @@ -168,6 +168,8 @@ all::
#
# Define NO_PERL if you do not want Perl scripts or libraries at all.
#
# Define NO_PYTHON if you do not want Python scripts or libraries at all.
#
# Define NO_TCLTK if you do not want Tcl/Tk GUI.
#
# The TCL_PATH variable governs the location of the Tcl interpreter
Expand Down Expand Up @@ -341,6 +343,7 @@ LIB_H =
LIB_OBJS =
PROGRAMS =
SCRIPT_PERL =
SCRIPT_PYTHON =
SCRIPT_SH =
TEST_PROGRAMS =

Expand Down Expand Up @@ -379,6 +382,7 @@ SCRIPT_PERL += git-svn.perl

SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
git-instaweb

# Empty...
Expand Down Expand Up @@ -434,8 +438,12 @@ endif
ifndef PERL_PATH
PERL_PATH = /usr/bin/perl
endif
ifndef PYTHON_PATH
PYTHON_PATH = /usr/bin/python
endif

export PERL_PATH
export PYTHON_PATH

LIB_FILE=libgit.a
XDIFF_LIB=xdiff/lib.a
Expand Down Expand Up @@ -1346,6 +1354,10 @@ ifeq ($(PERL_PATH),)
NO_PERL=NoThanks
endif

ifeq ($(PYTHON_PATH),)
NO_PYTHON=NoThanks
endif

QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =

Expand Down Expand Up @@ -1393,6 +1405,7 @@ prefix_SQ = $(subst ','\'',$(prefix))

SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))

LIBS = $(GITLIBS) $(EXTLIBS)
Expand Down Expand Up @@ -1439,6 +1452,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)

Expand Down Expand Up @@ -1566,11 +1582,41 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
mv $@+ $@
endif # NO_PERL


ifdef JSMIN
gitweb/gitweb.min.js: gitweb/gitweb.js
$(QUIET_GEN)$(JSMIN) <$< >$@
endif # JSMIN

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' \
Expand Down Expand Up @@ -1697,6 +1743,7 @@ GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@

### Detect Tck/Tk interpreter path changes
ifndef NO_TCLTK
Expand Down Expand Up @@ -1796,6 +1843,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
Expand Down Expand Up @@ -1912,6 +1962,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
Expand Down
3 changes: 2 additions & 1 deletion builtin-clone.c
Expand Up @@ -362,9 +362,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
const char *repo_name, *repo, *work_tree, *git_dir;
char *path, *dir;
int dest_exists;
const struct ref *refs, *remote_head, *mapped_refs;
const struct ref *refs, *remote_head;
const struct ref *remote_head_points_at;
const struct ref *our_head_points_at;
struct ref *mapped_refs;
struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
struct transport *transport = NULL;
Expand Down
7 changes: 5 additions & 2 deletions builtin-fetch.c
Expand Up @@ -322,7 +322,10 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
if (!fp)
return error("cannot open %s: %s\n", filename, strerror(errno));

url = transport_anonymize_url(raw_url);
if (raw_url)
url = transport_anonymize_url(raw_url);
else
url = xstrdup("foreign");
for (rm = ref_map; rm; rm = rm->next) {
struct ref *ref = NULL;

Expand Down Expand Up @@ -819,7 +822,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
if (!remote)
die("Where do you want to fetch from today?");

transport = transport_get(remote, remote->url[0]);
transport = transport_get(remote, NULL);
if (verbosity >= 2)
transport->verbose = verbosity <= 3 ? verbosity : 3;
if (verbosity < 0)
Expand Down
2 changes: 1 addition & 1 deletion builtin-ls-remote.c
Expand Up @@ -89,7 +89,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
remote = remote_get(dest);
if (!remote->url_nr)
die("remote %s has no configured URL", dest);
transport = transport_get(remote, remote->url[0]);
transport = transport_get(remote, NULL);
if (uploadpack != NULL)
transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);

Expand Down
69 changes: 43 additions & 26 deletions builtin-push.c
Expand Up @@ -87,6 +87,37 @@ static void setup_default_push_refspecs(void)
}
}

static int push_with_options(struct transport *transport, int flags)
{
int err;
int nonfastforward;
if (receivepack)
transport_set_option(transport,
TRANS_OPT_RECEIVEPACK, receivepack);
if (thin)
transport_set_option(transport, TRANS_OPT_THIN, "yes");

if (flags & TRANSPORT_PUSH_VERBOSE)
fprintf(stderr, "Pushing to %s\n", transport->url);
err = transport_push(transport, refspec_nr, refspec, flags,
&nonfastforward);
if (err != 0)
error("failed to push some refs to '%s'", transport->url);

err |= transport_disconnect(transport);

if (!err)
return 0;

if (nonfastforward && advice_push_nonfastforward) {
printf("To prevent you from losing history, non-fast-forward updates were rejected\n"
"Merge the remote changes before pushing again. See the 'non-fast-forward'\n"
"section of 'git push --help' for details.\n");
}

return 1;
}

static int do_push(const char *repo, int flags)
{
int i, errs;
Expand Down Expand Up @@ -135,33 +166,19 @@ static int do_push(const char *repo, int flags)
url = remote->url;
url_nr = remote->url_nr;
}
for (i = 0; i < url_nr; i++) {
struct transport *transport =
transport_get(remote, url[i]);
int err;
int nonfastforward;
if (receivepack)
transport_set_option(transport,
TRANS_OPT_RECEIVEPACK, receivepack);
if (thin)
transport_set_option(transport, TRANS_OPT_THIN, "yes");

if (flags & TRANSPORT_PUSH_VERBOSE)
fprintf(stderr, "Pushing to %s\n", url[i]);
err = transport_push(transport, refspec_nr, refspec, flags,
&nonfastforward);
err |= transport_disconnect(transport);

if (!err)
continue;

error("failed to push some refs to '%s'", url[i]);
if (nonfastforward && advice_push_nonfastforward) {
printf("To prevent you from losing history, non-fast-forward updates were rejected\n"
"Merge the remote changes before pushing again. See the 'non-fast-forward'\n"
"section of 'git push --help' for details.\n");
if (url_nr) {
for (i = 0; i < url_nr; i++) {
struct transport *transport =
transport_get(remote, url[i]);
if (push_with_options(transport, flags))
errs++;
}
errs++;
} else {
struct transport *transport =
transport_get(remote, NULL);

if (push_with_options(transport, flags))
errs++;
}
return !!errs;
}
Expand Down
3 changes: 3 additions & 0 deletions configure.ac
Expand Up @@ -276,6 +276,9 @@ GIT_ARG_SET_PATH(shell)
# Define PERL_PATH to provide path to Perl.
GIT_ARG_SET_PATH(perl)
#
# Define PYTHON_PATH to provide path to Python.
GIT_ARG_SET_PATH(python)
#
# Define ZLIB_PATH to provide path to zlib.
GIT_ARG_SET_PATH(zlib)
#
Expand Down
2 changes: 2 additions & 0 deletions git_remote_helpers/.gitignore
@@ -0,0 +1,2 @@
/build
/dist
35 changes: 35 additions & 0 deletions git_remote_helpers/Makefile
@@ -0,0 +1,35 @@
#
# 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
16 changes: 16 additions & 0 deletions git_remote_helpers/__init__.py
@@ -0,0 +1,16 @@
#!/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.
"""
Empty file.

0 comments on commit e74f43f

Please sign in to comment.