mirror of
https://github.com/git/git.git
synced 2026-04-01 20:40:08 +02:00
Merge branch 'master' of git://repo.or.cz/alt-git
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -104,6 +104,7 @@ git-receive-pack
|
||||
git-reflog
|
||||
git-relink
|
||||
git-remote
|
||||
git-remote-curl
|
||||
git-repack
|
||||
git-replace
|
||||
git-repo-config
|
||||
|
||||
29
Documentation/RelNotes-1.6.4.3.txt
Normal file
29
Documentation/RelNotes-1.6.4.3.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
GIT v1.6.4.3 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.4.2
|
||||
--------------------
|
||||
|
||||
* "git clone" from an empty repository gave unnecessary error message,
|
||||
even though it did everything else correctly.
|
||||
|
||||
* "git cvsserver" invoked git commands via "git-foo" style, which has long
|
||||
been deprecated.
|
||||
|
||||
* "git fetch" and "git clone" had an extra sanity check to verify the
|
||||
presense of the corresponding *.pack file before downloading *.idx
|
||||
file by issuing a HEAD request. Github server however sometimes
|
||||
gave 500 (Internal server error) response to HEAD even if a GET
|
||||
request for *.pack file to the same URL would have succeeded, and broke
|
||||
clone over HTTP from some of their repositories. As a workaround, this
|
||||
verification has been removed (as it is not absolutely necessary).
|
||||
|
||||
* "git grep" did not like relative pathname to refer outside the current
|
||||
directory when run from a subdirectory.
|
||||
|
||||
* an error message from "git push" was formatted in a very ugly way.
|
||||
|
||||
* "git svn" did not quote the subversion user name correctly when
|
||||
running its author-prog helper program.
|
||||
|
||||
Other minor documentation updates are included.
|
||||
@@ -38,6 +38,9 @@ Updates since v1.6.4
|
||||
|
||||
* more improvements on mingw port.
|
||||
|
||||
* mingw will also give FRSX as the default value for the LESS
|
||||
environment variable when the user does not have one.
|
||||
|
||||
(performance)
|
||||
|
||||
* On major platforms, the system can be compiled to use with Linus's
|
||||
@@ -48,11 +51,28 @@ Updates since v1.6.4
|
||||
* Unnecessary inefficiency in deepening of a shallow repository has
|
||||
been removed.
|
||||
|
||||
* The "git" main binary used to link with libcurl, which then dragged
|
||||
in a large number of external libraries. When using basic plumbing
|
||||
commands in scripts, this unnecessarily slowed things down. We now
|
||||
implement http/https/ftp transfer as a separate executable as we
|
||||
used to.
|
||||
|
||||
* "git clone" run locally hardlinks or copies the files in .git/ to
|
||||
newly created repository. It used to give new mtime to copied files,
|
||||
but this delayed garbage collection to trigger unnecessarily in the
|
||||
cloned repository. We now preserve mtime for these files to avoid
|
||||
this issue.
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* Human writable date format to various options, e.g. --since=yesterday,
|
||||
master@{2000.09.17}, are taught to infer some omitted input properly.
|
||||
|
||||
* A few programs gave verbose "advice" messages to help uninitiated
|
||||
people when issuing error messages. An infrastructure to allow
|
||||
users to squelch them has been introduced, and a few such messages
|
||||
can be silenced now.
|
||||
|
||||
* refs/replace/ hierarchy is designed to be usable as a replacement
|
||||
of the "grafts" mechanism, with the added advantage that it can be
|
||||
transferred across repositories.
|
||||
@@ -83,6 +103,8 @@ Updates since v1.6.4
|
||||
reordering commits and trees without touching the contents of
|
||||
blobs.
|
||||
|
||||
* "git fast-import" has a pair of new front-end in contrib/ area.
|
||||
|
||||
* "git init" learned to mkdir/chdir into a directory when given an
|
||||
extra argument (i.e. "git init this").
|
||||
|
||||
@@ -91,8 +113,16 @@ Updates since v1.6.4
|
||||
* "git log --decorate" can optionally be told with --decorate=full to
|
||||
give the reference name in full.
|
||||
|
||||
* "git merge" issued an unnecessarily scary message when it detected
|
||||
that the merge may have to touch the path that the user has local
|
||||
uncommitted changes to. The message has been reworded to make it
|
||||
clear that the command aborted, without doing any harm.
|
||||
|
||||
* "git push" can be told to be --quiet.
|
||||
|
||||
* "git push" pays attention to url.$base.pushInsteadOf and uses a URL
|
||||
that is derived from the URL used for fetching.
|
||||
|
||||
* informational output from "git reset" that lists the locally modified
|
||||
paths is made consistent with that of "git checkout $another_branch".
|
||||
|
||||
@@ -126,5 +156,6 @@ Fixes since v1.6.4
|
||||
--
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.4.2-298-gdf01e7c
|
||||
O=v1.6.5-rc0-49-g5f2b1e6
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master --not maint
|
||||
|
||||
@@ -113,6 +113,21 @@ For command-specific variables, you will find a more detailed description
|
||||
in the appropriate manual page. You will find a description of non-core
|
||||
porcelain configuration variables in the respective porcelain documentation.
|
||||
|
||||
advice.*::
|
||||
When set to 'true', display the given optional help message.
|
||||
When set to 'false', do not display. The configuration variables
|
||||
are:
|
||||
+
|
||||
--
|
||||
pushNonFastForward::
|
||||
Advice shown when linkgit:git-push[1] refuses
|
||||
non-fast-forward refs. Default: true.
|
||||
statusHints::
|
||||
Directions on how to stage/unstage/add shown in the
|
||||
output of linkgit:git-status[1] and the template shown
|
||||
when writing commit messages. Default: true.
|
||||
--
|
||||
|
||||
core.fileMode::
|
||||
If false, the executable bit differences between the index and
|
||||
the working copy are ignored; useful on broken filesystems like FAT.
|
||||
@@ -1500,6 +1515,19 @@ url.<base>.insteadOf::
|
||||
never-before-seen repository on the site. When more than one
|
||||
insteadOf strings match a given URL, the longest match is used.
|
||||
|
||||
url.<base>.pushInsteadOf::
|
||||
Any URL that starts with this value will not be pushed to;
|
||||
instead, it will be rewritten to start with <base>, and the
|
||||
resulting URL will be pushed to. In cases where some site serves
|
||||
a large number of repositories, and serves them with multiple
|
||||
access methods, some of which do not allow push, this feature
|
||||
allows people to specify a pull-only URL and have git
|
||||
automatically use an appropriate URL to push, even for a
|
||||
never-before-seen repository on the site. When more than one
|
||||
pushInsteadOf strings match a given URL, the longest match is
|
||||
used. If a remote has an explicit pushurl, git will ignore this
|
||||
setting for that remote.
|
||||
|
||||
user.email::
|
||||
Your email address to be recorded in any newly created commits.
|
||||
Can be overridden by the 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_EMAIL', and
|
||||
|
||||
@@ -72,9 +72,14 @@ OPTIONS
|
||||
|
||||
-p::
|
||||
--patch::
|
||||
Similar to Interactive mode but the initial command loop is
|
||||
bypassed and the 'patch' subcommand is invoked using each of
|
||||
the specified filepatterns before exiting.
|
||||
Interactively choose hunks of patch between the index and the
|
||||
work tree and add them to the index. This gives the user a chance
|
||||
to review the difference before adding modified contents to the
|
||||
index.
|
||||
|
||||
This effectively runs ``add --interactive``, but bypasses the
|
||||
initial command menu and directly jumps to `patch` subcommand.
|
||||
See ``Interactive mode'' for details.
|
||||
|
||||
-e, \--edit::
|
||||
Open the diff vs. the index in an editor and let the user
|
||||
|
||||
@@ -13,7 +13,7 @@ SYNOPSIS
|
||||
[--3way] [--interactive] [--committer-date-is-author-date]
|
||||
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||
[--reject] [-q | --quiet] [--scissors]
|
||||
[--reject] [-q | --quiet] [--scissors | --no-scissors]
|
||||
[<mbox> | <Maildir>...]
|
||||
'git am' (--skip | --resolved | --abort)
|
||||
|
||||
@@ -44,6 +44,9 @@ OPTIONS
|
||||
Remove everything in body before a scissors line (see
|
||||
linkgit:git-mailinfo[1]).
|
||||
|
||||
---no-scissors::
|
||||
Ignore scissors lines (see linkgit:git-mailinfo[1]).
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
Be quiet. Only print error messages.
|
||||
|
||||
@@ -62,6 +62,11 @@ This is useful if you want to begin your message in a discussion thread
|
||||
with comments and suggestions on the message you are responding to, and to
|
||||
conclude it with a patch submission, separating the discussion and the
|
||||
beginning of the proposed commit log message with a scissors line.
|
||||
+
|
||||
This can enabled by default with the configuration option mailinfo.scissors.
|
||||
|
||||
--no-scissors::
|
||||
Ignore scissors lines. Useful for overriding mailinfo.scissors settings.
|
||||
|
||||
<msg>::
|
||||
The commit log message extracted from e-mail, usually
|
||||
|
||||
@@ -9,7 +9,7 @@ git-quiltimport - Applies a quilt patchset onto the current branch
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
|
||||
'git quiltimport' [--dry-run | -n] [--author <author>] [--patches <dir>]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
71
Documentation/git-remote-helpers.txt
Normal file
71
Documentation/git-remote-helpers.txt
Normal file
@@ -0,0 +1,71 @@
|
||||
git-remote-helpers(1)
|
||||
=====================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-remote-helpers - Helper programs for interoperation with remote git
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git remote-<transport>' <remote>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
These programs are normally not used directly by end users, but are
|
||||
invoked by various git programs that interact with remote repositories
|
||||
when the repository they would operate on will be accessed using
|
||||
transport code not linked into the main git binary. Various particular
|
||||
helper programs will behave as documented here.
|
||||
|
||||
COMMANDS
|
||||
--------
|
||||
|
||||
Commands are given by the caller on the helper's standard input, one per line.
|
||||
|
||||
'capabilities'::
|
||||
Lists the capabilities of the helper, one per line, ending
|
||||
with a blank line.
|
||||
|
||||
'list'::
|
||||
Lists the refs, one per line, in the format "<value> <name>
|
||||
[<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
|
||||
a symref, or "?" to indicate that the helper could not get the
|
||||
value of the ref. A space-separated list of attributes follows
|
||||
the name; unrecognized attributes are ignored. After the
|
||||
complete list, outputs a blank line.
|
||||
|
||||
'fetch' <sha1> <name>::
|
||||
Fetches the given object, writing the necessary objects to the
|
||||
database. Outputs a blank line when the fetch is
|
||||
complete. Only objects which were reported in the ref list
|
||||
with a sha1 may be fetched this way.
|
||||
+
|
||||
Supported if the helper has the "fetch" 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
|
||||
completing a valid response for the current command.
|
||||
|
||||
Additional commands may be supported, as may be determined from
|
||||
capabilities reported by the helper.
|
||||
|
||||
CAPABILITIES
|
||||
------------
|
||||
|
||||
'fetch'::
|
||||
This helper supports the 'fetch' command.
|
||||
|
||||
REF LIST ATTRIBUTES
|
||||
-------------------
|
||||
|
||||
None are defined yet, but the caller must accept any which are supplied.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Documentation by Daniel Barkalow.
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
||||
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.6.4.2/git.html[documentation for release 1.6.4.2]
|
||||
* link:v1.6.4.3/git.html[documentation for release 1.6.4.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.4.3.txt[1.6.4.3],
|
||||
link:RelNotes-1.6.4.2.txt[1.6.4.2],
|
||||
link:RelNotes-1.6.4.1.txt[1.6.4.1],
|
||||
link:RelNotes-1.6.4.txt[1.6.4].
|
||||
|
||||
@@ -67,3 +67,21 @@ For example, with this:
|
||||
a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be
|
||||
rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".
|
||||
|
||||
If you want to rewrite URLs for push only, you can create a
|
||||
configuration section of the form:
|
||||
|
||||
------------
|
||||
[url "<actual url base>"]
|
||||
pushInsteadOf = <other url base>
|
||||
------------
|
||||
|
||||
For example, with this:
|
||||
|
||||
------------
|
||||
[url "ssh://example.org/"]
|
||||
pushInsteadOf = git://example.org/
|
||||
------------
|
||||
|
||||
a URL like "git://example.org/path/to/repo.git" will be rewritten to
|
||||
"ssh://example.org/path/to/repo.git" for pushes, but pulls will still
|
||||
use the original URL.
|
||||
|
||||
50
INSTALL
50
INSTALL
@@ -13,6 +13,10 @@ that uses $prefix, the built results have some paths encoded,
|
||||
which are derived from $prefix, so "make all; make prefix=/usr
|
||||
install" would not work.
|
||||
|
||||
The beginning of the Makefile documents many variables that affect the way
|
||||
git is built. You can override them either from the command line, or in a
|
||||
config.mak file.
|
||||
|
||||
Alternatively you can use autoconf generated ./configure script to
|
||||
set up install paths (via config.mak.autogen), so you can write instead
|
||||
|
||||
@@ -48,32 +52,42 @@ Issues of note:
|
||||
export GIT_EXEC_PATH PATH GITPERLLIB
|
||||
|
||||
- Git is reasonably self-sufficient, but does depend on a few external
|
||||
programs and libraries:
|
||||
programs and libraries. Git can be used without most of them by adding
|
||||
the approriate "NO_<LIBRARY>=YesPlease" to the make command line or
|
||||
config.mak file.
|
||||
|
||||
- "zlib", the compression library. Git won't build without it.
|
||||
|
||||
- "openssl". Unless you specify otherwise, you'll get the SHA1
|
||||
library from here.
|
||||
- "ssh" is used to push and pull over the net.
|
||||
|
||||
If you don't have openssl, you can use one of the SHA1 libraries
|
||||
that come with git (git includes the one from Mozilla, and has
|
||||
its own PowerPC and ARM optimized ones too - see the Makefile).
|
||||
- A POSIX-compliant shell is required to run many scripts needed
|
||||
for everyday use (e.g. "bisect", "pull").
|
||||
|
||||
- libcurl library; git-http-fetch and git-fetch use them. You
|
||||
- "Perl" is needed to use some of the features (e.g. preparing a
|
||||
partial commit using "git add -i/-p", interacting with svn
|
||||
repositories with "git svn"). If you can live without these, use
|
||||
NO_PERL.
|
||||
|
||||
- "openssl" library is used by git-imap-send to use IMAP over SSL.
|
||||
If you don't need it, use NO_OPENSSL.
|
||||
|
||||
By default, git uses OpenSSL for SHA1 but it will use it's own
|
||||
library (inspired by Mozilla's) with either NO_OPENSSL or
|
||||
BLK_SHA1. Also included is a version optimized for PowerPC
|
||||
(PPC_SHA1).
|
||||
|
||||
- "libcurl" library is used by git-http-fetch and git-fetch. You
|
||||
might also want the "curl" executable for debugging purposes.
|
||||
If you do not use http transfer, you are probably OK if you
|
||||
do not have them.
|
||||
If you do not use http:// or https:// repositories, you do not
|
||||
have to have them (use NO_CURL).
|
||||
|
||||
- expat library; git-http-push uses it for remote lock
|
||||
management over DAV. Similar to "curl" above, this is optional.
|
||||
- "expat" library; git-http-push uses it for remote lock
|
||||
management over DAV. Similar to "curl" above, this is optional
|
||||
(with NO_EXPAT).
|
||||
|
||||
- "wish", the Tcl/Tk windowing shell is used in gitk to show the
|
||||
history graphically, and in git-gui.
|
||||
|
||||
- "ssh" is used to push and pull over the net
|
||||
|
||||
- "perl" and POSIX-compliant shells are needed to use most of
|
||||
the bare-bones Porcelainish scripts.
|
||||
- "wish", the Tcl/Tk windowing shell is used in gitk to show the
|
||||
history graphically, and in git-gui. If you don't want gitk or
|
||||
git-gui, you can use NO_TCLTK.
|
||||
|
||||
- Some platform specific issues are dealt with Makefile rules,
|
||||
but depending on your specific installation, you may not
|
||||
|
||||
30
Makefile
30
Makefile
@@ -91,7 +91,9 @@ all::
|
||||
# Define PPC_SHA1 environment variable when running make to make use of
|
||||
# a bundled SHA1 routine optimized for PowerPC.
|
||||
#
|
||||
# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
|
||||
# Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
|
||||
#
|
||||
# Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
|
||||
#
|
||||
# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
|
||||
#
|
||||
@@ -378,7 +380,8 @@ BUILT_INS += git-stage$X
|
||||
BUILT_INS += git-status$X
|
||||
BUILT_INS += git-whatchanged$X
|
||||
|
||||
# what 'all' will build and 'install' will install, in gitexecdir
|
||||
# what 'all' will build and 'install' will install in gitexecdir,
|
||||
# excluding programs for built-in commands
|
||||
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
|
||||
|
||||
# what 'all' will build but not install in gitexecdir
|
||||
@@ -397,6 +400,7 @@ export PERL_PATH
|
||||
LIB_FILE=libgit.a
|
||||
XDIFF_LIB=xdiff/lib.a
|
||||
|
||||
LIB_H += advice.h
|
||||
LIB_H += archive.h
|
||||
LIB_H += attr.h
|
||||
LIB_H += blob.h
|
||||
@@ -454,6 +458,7 @@ LIB_H += utf8.h
|
||||
LIB_H += wt-status.h
|
||||
|
||||
LIB_OBJS += abspath.o
|
||||
LIB_OBJS += advice.o
|
||||
LIB_OBJS += alias.o
|
||||
LIB_OBJS += alloc.o
|
||||
LIB_OBJS += archive.o
|
||||
@@ -545,6 +550,7 @@ LIB_OBJS += symlinks.o
|
||||
LIB_OBJS += tag.o
|
||||
LIB_OBJS += trace.o
|
||||
LIB_OBJS += transport.o
|
||||
LIB_OBJS += transport-helper.o
|
||||
LIB_OBJS += tree-diff.o
|
||||
LIB_OBJS += tree.o
|
||||
LIB_OBJS += tree-walk.o
|
||||
@@ -704,6 +710,7 @@ ifeq ($(uname_S),SCO_SV)
|
||||
TAR = gtar
|
||||
endif
|
||||
ifeq ($(uname_S),Darwin)
|
||||
NEEDS_CRYPTO_WITH_SSL = YesPlease
|
||||
NEEDS_SSL_WITH_CRYPTO = YesPlease
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
|
||||
@@ -970,9 +977,7 @@ else
|
||||
else
|
||||
CURL_LIBCURL = -lcurl
|
||||
endif
|
||||
BUILTIN_OBJS += builtin-http-fetch.o
|
||||
EXTLIBS += $(CURL_LIBCURL)
|
||||
LIB_OBJS += http.o http-walker.o
|
||||
PROGRAMS += git-remote-curl$X git-http-fetch$X
|
||||
curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
|
||||
ifeq "$(curl_check)" "070908"
|
||||
ifndef NO_EXPAT
|
||||
@@ -1007,6 +1012,9 @@ ifndef NO_OPENSSL
|
||||
else
|
||||
OPENSSL_LINK =
|
||||
endif
|
||||
ifdef NEEDS_CRYPTO_WITH_SSL
|
||||
OPENSSL_LINK += -lcrypto
|
||||
endif
|
||||
else
|
||||
BASIC_CFLAGS += -DNO_OPENSSL
|
||||
BLK_SHA1 = 1
|
||||
@@ -1243,6 +1251,7 @@ ifndef V
|
||||
QUIET_LINK = @echo ' ' LINK $@;
|
||||
QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
|
||||
QUIET_GEN = @echo ' ' GEN $@;
|
||||
QUIET_LNCP = @echo ' ' LN/CP $@;
|
||||
QUIET_SUBDIR0 = +@subdir=
|
||||
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
|
||||
$(MAKE) $(PRINT_DIR) -C $$subdir
|
||||
@@ -1470,12 +1479,21 @@ git-imap-send$X: imap-send.o $(GITLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
|
||||
|
||||
http.o http-walker.o http-push.o transport.o: http.h
|
||||
http.o http-walker.o http-push.o: http.h
|
||||
|
||||
http.o http-walker.o: $(LIB_H)
|
||||
|
||||
git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(CURL_LIBCURL)
|
||||
git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
|
||||
|
||||
git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
|
||||
|
||||
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
|
||||
$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
|
||||
builtin-revert.o wt-status.o: wt-status.h
|
||||
|
||||
27
advice.c
Normal file
27
advice.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "cache.h"
|
||||
|
||||
int advice_push_nonfastforward = 1;
|
||||
int advice_status_hints = 1;
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
int *preference;
|
||||
} advice_config[] = {
|
||||
{ "pushnonfastforward", &advice_push_nonfastforward },
|
||||
{ "statushints", &advice_status_hints },
|
||||
};
|
||||
|
||||
int git_default_advice_config(const char *var, const char *value)
|
||||
{
|
||||
const char *k = skip_prefix(var, "advice.");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
|
||||
if (strcmp(k, advice_config[i].name))
|
||||
continue;
|
||||
*advice_config[i].preference = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
advice.h
Normal file
9
advice.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef ADVICE_H
|
||||
#define ADVICE_H
|
||||
|
||||
extern int advice_push_nonfastforward;
|
||||
extern int advice_status_hints;
|
||||
|
||||
int git_default_advice_config(const char *var, const char *value);
|
||||
|
||||
#endif /* ADVICE_H */
|
||||
@@ -198,7 +198,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
|
||||
out = open(file, O_CREAT | O_WRONLY, 0644);
|
||||
if (out < 0)
|
||||
die ("Could not open '%s' for writing.", file);
|
||||
rev.diffopt.file = fdopen(out, "w");
|
||||
rev.diffopt.file = xfdopen(out, "w");
|
||||
rev.diffopt.close_file = 1;
|
||||
if (run_diff_files(&rev, 0))
|
||||
die ("Could not write patch");
|
||||
|
||||
@@ -269,7 +269,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
|
||||
die_errno("failed to create link '%s'", dest->buf);
|
||||
option_no_hardlinks = 1;
|
||||
}
|
||||
if (copy_file(dest->buf, src->buf, 0666))
|
||||
if (copy_file_with_time(dest->buf, src->buf, 0666))
|
||||
die_errno("failed to copy file to '%s'", dest->buf);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
@@ -454,7 +454,7 @@ static int quickfetch(struct ref *ref_map)
|
||||
|
||||
for (ref = ref_map; ref; ref = ref->next) {
|
||||
if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 ||
|
||||
write_in_full(revlist.in, "\n", 1) < 0) {
|
||||
write_str_in_full(revlist.in, "\n") < 0) {
|
||||
if (errno != EPIPE && errno != EINVAL)
|
||||
error("failed write to rev-list: %s", strerror(errno));
|
||||
err = -1;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "parse-options.h"
|
||||
#include "userdiff.h"
|
||||
#include "grep.h"
|
||||
#include "quote.h"
|
||||
|
||||
#ifndef NO_EXTERNAL_GREP
|
||||
#ifdef __unix__
|
||||
@@ -157,8 +158,8 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
|
||||
unsigned long size;
|
||||
char *data;
|
||||
enum object_type type;
|
||||
char *to_free = NULL;
|
||||
int hit;
|
||||
struct strbuf pathbuf = STRBUF_INIT;
|
||||
|
||||
data = read_sha1_file(sha1, &type, &size);
|
||||
if (!data) {
|
||||
@@ -166,26 +167,13 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
|
||||
return 0;
|
||||
}
|
||||
if (opt->relative && opt->prefix_length) {
|
||||
static char name_buf[PATH_MAX];
|
||||
char *cp;
|
||||
int name_len = strlen(name) - opt->prefix_length + 1;
|
||||
|
||||
if (!tree_name_len)
|
||||
name += opt->prefix_length;
|
||||
else {
|
||||
if (ARRAY_SIZE(name_buf) <= name_len)
|
||||
cp = to_free = xmalloc(name_len);
|
||||
else
|
||||
cp = name_buf;
|
||||
memcpy(cp, name, tree_name_len);
|
||||
strcpy(cp + tree_name_len,
|
||||
name + tree_name_len + opt->prefix_length);
|
||||
name = cp;
|
||||
}
|
||||
quote_path_relative(name + tree_name_len, -1, &pathbuf, opt->prefix);
|
||||
strbuf_insert(&pathbuf, 0, name, tree_name_len);
|
||||
name = pathbuf.buf;
|
||||
}
|
||||
hit = grep_buffer(opt, name, data, size);
|
||||
strbuf_release(&pathbuf);
|
||||
free(data);
|
||||
free(to_free);
|
||||
return hit;
|
||||
}
|
||||
|
||||
@@ -195,6 +183,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
|
||||
int i;
|
||||
char *data;
|
||||
size_t sz;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (lstat(filename, &st) < 0) {
|
||||
err_ret:
|
||||
@@ -219,8 +208,9 @@ static int grep_file(struct grep_opt *opt, const char *filename)
|
||||
}
|
||||
close(i);
|
||||
if (opt->relative && opt->prefix_length)
|
||||
filename += opt->prefix_length;
|
||||
filename = quote_path_relative(filename, -1, &buf, opt->prefix);
|
||||
i = grep_buffer(opt, filename, data, sz);
|
||||
strbuf_release(&buf);
|
||||
free(data);
|
||||
return i;
|
||||
}
|
||||
@@ -503,6 +493,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
|
||||
hit = external_grep(opt, paths, cached);
|
||||
if (hit >= 0)
|
||||
return hit;
|
||||
hit = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -798,6 +789,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
opt.prefix = prefix;
|
||||
opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
|
||||
opt.relative = 1;
|
||||
opt.pathname = 1;
|
||||
@@ -868,15 +860,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
verify_filename(prefix, argv[j]);
|
||||
}
|
||||
|
||||
if (i < argc) {
|
||||
if (i < argc)
|
||||
paths = get_pathspec(prefix, argv + i);
|
||||
if (opt.prefix_length && opt.relative) {
|
||||
/* Make sure we do not get outside of paths */
|
||||
for (i = 0; paths[i]; i++)
|
||||
if (strncmp(prefix, paths[i], opt.prefix_length))
|
||||
die("git grep: cannot generate relative filenames containing '..'");
|
||||
}
|
||||
}
|
||||
else if (prefix) {
|
||||
paths = xcalloc(2, sizeof(const char *));
|
||||
paths[0] = prefix;
|
||||
|
||||
@@ -1004,7 +1004,7 @@ static int git_mailinfo_config(const char *var, const char *value, void *unused)
|
||||
}
|
||||
|
||||
static const char mailinfo_usage[] =
|
||||
"git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
|
||||
"git mailinfo [-k] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] msg patch < mail >info";
|
||||
|
||||
int cmd_mailinfo(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
|
||||
fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||
if (fd < 0)
|
||||
die_errno("cannot open output file '%s'", name);
|
||||
output = fdopen(fd, "w");
|
||||
output = xfdopen(fd, "w");
|
||||
|
||||
/* Copy it out, while searching for a line that begins with
|
||||
* "From " and having something that looks like a date format.
|
||||
|
||||
@@ -157,7 +157,7 @@ static int do_push(const char *repo, int flags)
|
||||
continue;
|
||||
|
||||
error("failed to push some refs to '%s'", url[i]);
|
||||
if (nonfastforward) {
|
||||
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");
|
||||
|
||||
@@ -362,7 +362,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
|
||||
} else if (cmd->updateref &&
|
||||
(write_in_full(lock->lock_fd,
|
||||
sha1_to_hex(cb.last_kept_sha1), 40) != 40 ||
|
||||
write_in_full(lock->lock_fd, "\n", 1) != 1 ||
|
||||
write_str_in_full(lock->lock_fd, "\n") != 1 ||
|
||||
close_ref(lock) < 0)) {
|
||||
status |= error("Couldn't write %s",
|
||||
lock->lk->filename);
|
||||
|
||||
2
bundle.c
2
bundle.c
@@ -234,7 +234,7 @@ int create_bundle(struct bundle_header *header, const char *path,
|
||||
rls.git_cmd = 1;
|
||||
if (start_command(&rls))
|
||||
return -1;
|
||||
rls_fout = fdopen(rls.out, "r");
|
||||
rls_fout = xfdopen(rls.out, "r");
|
||||
while (fgets(buffer, sizeof(buffer), rls_fout)) {
|
||||
unsigned char sha1[20];
|
||||
if (buffer[0] == '-') {
|
||||
|
||||
11
cache.h
11
cache.h
@@ -4,6 +4,7 @@
|
||||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
#include "hash.h"
|
||||
#include "advice.h"
|
||||
|
||||
#include SHA1_HEADER
|
||||
#ifndef git_SHA_CTX
|
||||
@@ -923,13 +924,19 @@ extern const char *git_mailmap_file;
|
||||
extern void maybe_flush_or_die(FILE *, const char *);
|
||||
extern int copy_fd(int ifd, int ofd);
|
||||
extern int copy_file(const char *dst, const char *src, int mode);
|
||||
extern ssize_t read_in_full(int fd, void *buf, size_t count);
|
||||
extern ssize_t write_in_full(int fd, const void *buf, size_t count);
|
||||
extern int copy_file_with_time(const char *dst, const char *src, int mode);
|
||||
extern void write_or_die(int fd, const void *buf, size_t count);
|
||||
extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
|
||||
extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
|
||||
extern void fsync_or_die(int fd, const char *);
|
||||
|
||||
extern ssize_t read_in_full(int fd, void *buf, size_t count);
|
||||
extern ssize_t write_in_full(int fd, const void *buf, size_t count);
|
||||
static inline ssize_t write_str_in_full(int fd, const char *str)
|
||||
{
|
||||
return write_in_full(fd, str, strlen(str));
|
||||
}
|
||||
|
||||
/* pager.c */
|
||||
extern void setup_pager(void);
|
||||
extern const char *pager_program;
|
||||
|
||||
2
commit.c
2
commit.c
@@ -212,7 +212,7 @@ int write_shallow_commits(int fd, int use_pack_protocol)
|
||||
else {
|
||||
if (write_in_full(fd, hex, 40) != 40)
|
||||
break;
|
||||
if (write_in_full(fd, "\n", 1) != 1)
|
||||
if (write_str_in_full(fd, "\n") != 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,7 +824,7 @@ void mingw_execvp(const char *cmd, char *const *argv)
|
||||
free_path_split(path);
|
||||
}
|
||||
|
||||
char **copy_environ()
|
||||
static char **copy_environ(void)
|
||||
{
|
||||
char **env;
|
||||
int i = 0;
|
||||
@@ -861,7 +861,7 @@ static int lookup_env(char **env, const char *name, size_t nmln)
|
||||
/*
|
||||
* If name contains '=', then sets the variable, otherwise it unsets it
|
||||
*/
|
||||
char **env_setenv(char **env, const char *name)
|
||||
static char **env_setenv(char **env, const char *name)
|
||||
{
|
||||
char *eq = strchrnul(name, '=');
|
||||
int i = lookup_env(env, name, eq-name);
|
||||
@@ -886,6 +886,18 @@ char **env_setenv(char **env, const char *name)
|
||||
return env;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies global environ and adjusts variables as specified by vars.
|
||||
*/
|
||||
char **make_augmented_environ(const char *const *vars)
|
||||
{
|
||||
char **env = copy_environ();
|
||||
|
||||
while (*vars)
|
||||
env = env_setenv(env, *vars++);
|
||||
return env;
|
||||
}
|
||||
|
||||
/* this is the first function to call into WS_32; initialize it */
|
||||
#undef gethostbyname
|
||||
struct hostent *mingw_gethostbyname(const char *host)
|
||||
|
||||
@@ -222,9 +222,8 @@ void mingw_open_html(const char *path);
|
||||
* helpers
|
||||
*/
|
||||
|
||||
char **copy_environ(void);
|
||||
char **make_augmented_environ(const char *const *vars);
|
||||
void free_environ(char **env);
|
||||
char **env_setenv(char **env, const char *name);
|
||||
|
||||
/*
|
||||
* A replacement of main() that ensures that argv[0] has a path
|
||||
|
||||
5
config.c
5
config.c
@@ -627,6 +627,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
|
||||
if (!prefixcmp(var, "mailmap."))
|
||||
return git_default_mailmap_config(var, value);
|
||||
|
||||
if (!prefixcmp(var, "advice."))
|
||||
return git_default_advice_config(var, value);
|
||||
|
||||
if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
|
||||
pager_use_color = git_config_bool(var,value);
|
||||
return 0;
|
||||
@@ -1116,7 +1119,7 @@ int git_config_set_multivar(const char *key, const char *value,
|
||||
copy_end - copy_begin)
|
||||
goto write_err_out;
|
||||
if (new_line &&
|
||||
write_in_full(fd, "\n", 1) != 1)
|
||||
write_str_in_full(fd, "\n") != 1)
|
||||
goto write_err_out;
|
||||
}
|
||||
copy_begin = store.offset[i];
|
||||
|
||||
@@ -1532,7 +1532,7 @@ _git_config ()
|
||||
url.*.*)
|
||||
local pfx="${cur%.*}."
|
||||
cur="${cur##*.}"
|
||||
__gitcomp "insteadof" "$pfx" "$cur"
|
||||
__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1046,7 +1046,7 @@ The FILES list must be sorted."
|
||||
(defun git-add-file ()
|
||||
"Add marked file(s) to the index cache."
|
||||
(interactive)
|
||||
(let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored))))
|
||||
(let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored 'unmerged))))
|
||||
;; FIXME: add support for directories
|
||||
(unless files
|
||||
(push (file-relative-name (read-file-name "File to add: " nil nil t)) files))
|
||||
@@ -1119,15 +1119,6 @@ The FILES list must be sorted."
|
||||
(when buffer (with-current-buffer buffer (revert-buffer t t t)))))
|
||||
(git-success-message "Reverted" names))))))
|
||||
|
||||
(defun git-resolve-file ()
|
||||
"Resolve conflicts in marked file(s)."
|
||||
(interactive)
|
||||
(let ((files (git-get-filenames (git-marked-files-state 'unmerged))))
|
||||
(when files
|
||||
(when (apply 'git-call-process-display-error "update-index" "--" files)
|
||||
(git-update-status-files files)
|
||||
(git-success-message "Resolved" files)))))
|
||||
|
||||
(defun git-remove-handled ()
|
||||
"Remove handled files from the status list."
|
||||
(interactive)
|
||||
@@ -1556,7 +1547,6 @@ amended version of it."
|
||||
(define-key map "P" 'git-prev-unmerged-file)
|
||||
(define-key map "q" 'git-status-quit)
|
||||
(define-key map "r" 'git-remove-file)
|
||||
(define-key map "R" 'git-resolve-file)
|
||||
(define-key map "t" toggle-map)
|
||||
(define-key map "T" 'git-toggle-all-marks)
|
||||
(define-key map "u" 'git-unmark-file)
|
||||
@@ -1598,7 +1588,6 @@ amended version of it."
|
||||
("Merge"
|
||||
["Next Unmerged File" git-next-unmerged-file t]
|
||||
["Prev Unmerged File" git-prev-unmerged-file t]
|
||||
["Mark as Resolved" git-resolve-file t]
|
||||
["Interactive Merge File" git-find-file-imerge t]
|
||||
["Diff Against Common Base File" git-diff-file-base t]
|
||||
["Diff Combined" git-diff-file-combined t]
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
# License: MIT <http://www.opensource.org/licenses/mit-license.php>
|
||||
#
|
||||
|
||||
import optparse, sys, os, marshal, popen2, subprocess, shelve
|
||||
import tempfile, getopt, sha, os.path, time, platform
|
||||
import optparse, sys, os, marshal, subprocess, shelve
|
||||
import tempfile, getopt, os.path, time, platform
|
||||
import re
|
||||
|
||||
from sets import Set;
|
||||
|
||||
verbose = False
|
||||
|
||||
|
||||
@@ -864,8 +862,8 @@ class P4Sync(Command):
|
||||
|
||||
self.usage += " //depot/path[@revRange]"
|
||||
self.silent = False
|
||||
self.createdBranches = Set()
|
||||
self.committedChanges = Set()
|
||||
self.createdBranches = set()
|
||||
self.committedChanges = set()
|
||||
self.branch = ""
|
||||
self.detectBranches = False
|
||||
self.detectLabels = False
|
||||
@@ -1662,7 +1660,7 @@ class P4Sync(Command):
|
||||
|
||||
if len(self.changesFile) > 0:
|
||||
output = open(self.changesFile).readlines()
|
||||
changeSet = Set()
|
||||
changeSet = set()
|
||||
for line in output:
|
||||
changeSet.add(int(line))
|
||||
|
||||
|
||||
416
contrib/fast-import/import-directories.perl
Executable file
416
contrib/fast-import/import-directories.perl
Executable file
@@ -0,0 +1,416 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Copyright 2008-2009 Peter Krefting <peter@softwolves.pp.se>
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
import-directories - Import bits and pieces to Git.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<import-directories.perl> F<configfile> F<outputfile>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Script to import arbitrary projects version controlled by the "copy the
|
||||
source directory to a new location and edit it there"-version controlled
|
||||
projects into version control. Handles projects with arbitrary branching
|
||||
and version trees, taking a file describing the inputs and generating a
|
||||
file compatible with the L<git-fast-import(1)> format.
|
||||
|
||||
=head1 CONFIGURATION FILE
|
||||
|
||||
=head2 Format
|
||||
|
||||
The configuration file is based on the standard I<.ini> format.
|
||||
|
||||
; Comments start with semi-colons
|
||||
[section]
|
||||
key=value
|
||||
|
||||
Please see below for information on how to escape special characters.
|
||||
|
||||
=head2 Global configuration
|
||||
|
||||
Global configuration is done in the B<[config]> section, which should be
|
||||
the first section in the file. Configuration can be changed by
|
||||
repeating configuration sections later on.
|
||||
|
||||
[config]
|
||||
; configure conversion of CRLFs. "convert" means that all CRLFs
|
||||
; should be converted into LFs (suitable for the core.autocrlf
|
||||
; setting set to true in Git). "none" means that all data is
|
||||
; treated as binary.
|
||||
crlf=convert
|
||||
|
||||
=head2 Revision configuration
|
||||
|
||||
Each revision that is to be imported is described in three
|
||||
sections. Revisions should be defined in topological order, so
|
||||
that a revision's parent has always been defined when a new revision
|
||||
is introduced. All the sections for one revision must be defined
|
||||
before defining the next revision.
|
||||
|
||||
Each revision is assigned a unique numerical identifier. The
|
||||
numbers do not need to be consecutive, nor monotonically
|
||||
increasing.
|
||||
|
||||
For instance, if your configuration file contains only the two
|
||||
revisions 4711 and 42, where 4711 is the initial commit, the
|
||||
only requirement is that 4711 is completely defined before 42.
|
||||
|
||||
=pod
|
||||
|
||||
=head3 Revision description section
|
||||
|
||||
A section whose section name is just an integer gives meta-data
|
||||
about the revision.
|
||||
|
||||
[3]
|
||||
; author sets the author of the revisions
|
||||
author=Peter Krefting <peter@softwolves.pp.se>
|
||||
; branch sets the branch that the revision should be committed to
|
||||
branch=master
|
||||
; parent describes the revision that is the parent of this commit
|
||||
; (optional)
|
||||
parent=1
|
||||
; merges describes a revision that is merged into this commit
|
||||
; (optional; can be repeated)
|
||||
merges=2
|
||||
; selects one file to take the timestamp from
|
||||
; (optional; if unspecified, the most recent file from the .files
|
||||
; section is used)
|
||||
timestamp=3/source.c
|
||||
|
||||
=head3 Revision contents section
|
||||
|
||||
A section whose section name is an integer followed by B<.files>
|
||||
describe all the files included in this revision. If a file that
|
||||
was available previously is not included in this revision, it will
|
||||
be removed.
|
||||
|
||||
If an on-disk revision is incomplete, you can point to files from
|
||||
a previous revision. There are no restriction as to where the source
|
||||
files are located, nor to the names of them.
|
||||
|
||||
[3.files]
|
||||
; the key is the path inside the repository, the value is the path
|
||||
; as seen from the importer script.
|
||||
source.c=ver-3.00/source.c
|
||||
source.h=ver-2.99/source.h
|
||||
readme.txt=ver-3.00/introduction to the project.txt
|
||||
|
||||
File names are treated as byte strings (but please see below on
|
||||
quoting rules), and should be stored in the configuration file in
|
||||
the encoding that should be used in the generated repository.
|
||||
|
||||
=head3 Revision commit message section
|
||||
|
||||
A section whose section name is an integer followed by B<.message>
|
||||
gives the commit message. This section is read verbatim, up until
|
||||
the beginning of the next section. As such, a commit message may not
|
||||
contain a line that begins with an opening square bracket ("[") and
|
||||
ends with a closing square bracket ("]"), unless they are surrounded
|
||||
by whitespace or other characters.
|
||||
|
||||
[3.message]
|
||||
Implement foobar.
|
||||
; trailing blank lines are ignored.
|
||||
|
||||
=cut
|
||||
|
||||
# Globals
|
||||
use strict;
|
||||
use integer;
|
||||
my $crlfmode = 0;
|
||||
my @revs;
|
||||
my (%revmap, %message, %files, %author, %branch, %parent, %merges, %time, %timesource);
|
||||
my $sectiontype = 0;
|
||||
my $rev = 0;
|
||||
my $mark = 1;
|
||||
|
||||
# Check command line
|
||||
if ($#ARGV < 1 || $ARGV[0] =~ /^--?h/)
|
||||
{
|
||||
exec('perldoc', $0);
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Open configuration
|
||||
my $config = $ARGV[0];
|
||||
open CFG, '<', $config or die "Cannot open configuration file \"$config\": ";
|
||||
|
||||
# Open output
|
||||
my $output = $ARGV[1];
|
||||
open OUT, '>', $output or die "Cannot create output file \"$output\": ";
|
||||
binmode OUT;
|
||||
|
||||
LINE: while (my $line = <CFG>)
|
||||
{
|
||||
$line =~ s/\r?\n$//;
|
||||
next LINE if $sectiontype != 4 && $line eq '';
|
||||
next LINE if $line =~ /^;/;
|
||||
my $oldsectiontype = $sectiontype;
|
||||
my $oldrev = $rev;
|
||||
|
||||
# Sections
|
||||
if ($line =~ m"^\[(config|(\d+)(|\.files|\.message))\]$")
|
||||
{
|
||||
if ($1 eq 'config')
|
||||
{
|
||||
$sectiontype = 1;
|
||||
}
|
||||
elsif ($3 eq '')
|
||||
{
|
||||
$sectiontype = 2;
|
||||
$rev = $2;
|
||||
# Create a new revision
|
||||
die "Duplicate rev: $line\n " if defined $revmap{$rev};
|
||||
print "Reading revision $rev\n";
|
||||
push @revs, $rev;
|
||||
$revmap{$rev} = $mark ++;
|
||||
$time{$revmap{$rev}} = 0;
|
||||
}
|
||||
elsif ($3 eq '.files')
|
||||
{
|
||||
$sectiontype = 3;
|
||||
$rev = $2;
|
||||
die "Revision mismatch: $line\n " unless $rev == $oldrev;
|
||||
}
|
||||
elsif ($3 eq '.message')
|
||||
{
|
||||
$sectiontype = 4;
|
||||
$rev = $2;
|
||||
die "Revision mismatch: $line\n " unless $rev == $oldrev;
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Internal parse error: $line\n ";
|
||||
}
|
||||
next LINE;
|
||||
}
|
||||
|
||||
# Parse data
|
||||
if ($sectiontype != 4)
|
||||
{
|
||||
# Key and value
|
||||
if ($line =~ m"^\s*([^\s].*=.*[^\s])\s*$")
|
||||
{
|
||||
my ($key, $value) = &parsekeyvaluepair($1);
|
||||
# Global configuration
|
||||
if (1 == $sectiontype)
|
||||
{
|
||||
if ($key eq 'crlf')
|
||||
{
|
||||
$crlfmode = 1, next LINE if $value eq 'convert';
|
||||
$crlfmode = 0, next LINE if $value eq 'none';
|
||||
}
|
||||
die "Unknown configuration option: $line\n ";
|
||||
}
|
||||
# Revision specification
|
||||
if (2 == $sectiontype)
|
||||
{
|
||||
my $current = $revmap{$rev};
|
||||
$author{$current} = $value, next LINE if $key eq 'author';
|
||||
$branch{$current} = $value, next LINE if $key eq 'branch';
|
||||
$parent{$current} = $value, next LINE if $key eq 'parent';
|
||||
$timesource{$current} = $value, next LINE if $key eq 'timestamp';
|
||||
push(@{$merges{$current}}, $value), next LINE if $key eq 'merges';
|
||||
die "Unknown revision option: $line\n ";
|
||||
}
|
||||
# Filespecs
|
||||
if (3 == $sectiontype)
|
||||
{
|
||||
# Add the file and create a marker
|
||||
die "File not found: $line\n " unless -f $value;
|
||||
my $current = $revmap{$rev};
|
||||
${$files{$current}}{$key} = $mark;
|
||||
my $time = &fileblob($value, $crlfmode, $mark ++);
|
||||
|
||||
# Update revision timestamp if more recent than other
|
||||
# files seen, or if this is the file we have selected
|
||||
# to take the time stamp from using the "timestamp"
|
||||
# directive.
|
||||
if ((defined $timesource{$current} && $timesource{$current} eq $value)
|
||||
|| $time > $time{$current})
|
||||
{
|
||||
$time{$current} = $time;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Parse error: $line\n ";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# Commit message
|
||||
my $current = $revmap{$rev};
|
||||
if (defined $message{$current})
|
||||
{
|
||||
$message{$current} .= "\n";
|
||||
}
|
||||
$message{$current} .= $line;
|
||||
}
|
||||
}
|
||||
close CFG;
|
||||
|
||||
# Start spewing out data for git-fast-import
|
||||
foreach my $commit (@revs)
|
||||
{
|
||||
# Progress
|
||||
print OUT "progress Creating revision $commit\n";
|
||||
|
||||
# Create commit header
|
||||
my $mark = $revmap{$commit};
|
||||
|
||||
# Branch and commit id
|
||||
print OUT "commit refs/heads/", $branch{$mark}, "\nmark :", $mark, "\n";
|
||||
|
||||
# Author and timestamp
|
||||
die "No timestamp defined for $commit (no files?)\n" unless defined $time{$mark};
|
||||
print OUT "committer ", $author{$mark}, " ", $time{$mark}, " +0100\n";
|
||||
|
||||
# Commit message
|
||||
die "No message defined for $commit\n" unless defined $message{$mark};
|
||||
my $message = $message{$mark};
|
||||
$message =~ s/\n$//; # Kill trailing empty line
|
||||
print OUT "data ", length($message), "\n", $message, "\n";
|
||||
|
||||
# Parent and any merges
|
||||
print OUT "from :", $revmap{$parent{$mark}}, "\n" if defined $parent{$mark};
|
||||
if (defined $merges{$mark})
|
||||
{
|
||||
foreach my $merge (@{$merges{$mark}})
|
||||
{
|
||||
print OUT "merge :", $revmap{$merge}, "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Output file marks
|
||||
print OUT "deleteall\n"; # start from scratch
|
||||
foreach my $file (sort keys %{$files{$mark}})
|
||||
{
|
||||
print OUT "M 644 :", ${$files{$mark}}{$file}, " $file\n";
|
||||
}
|
||||
print OUT "\n";
|
||||
}
|
||||
|
||||
# Create one file blob
|
||||
sub fileblob
|
||||
{
|
||||
my ($filename, $crlfmode, $mark) = @_;
|
||||
|
||||
# Import the file
|
||||
print OUT "progress Importing $filename\nblob\nmark :$mark\n";
|
||||
open FILE, '<', $filename or die "Cannot read $filename\n ";
|
||||
binmode FILE;
|
||||
my ($size, $mtime) = (stat(FILE))[7,9];
|
||||
my $file;
|
||||
read FILE, $file, $size;
|
||||
close FILE;
|
||||
$file =~ s/\r\n/\n/g if $crlfmode;
|
||||
print OUT "data ", length($file), "\n", $file, "\n";
|
||||
|
||||
return $mtime;
|
||||
}
|
||||
|
||||
# Parse a key=value pair
|
||||
sub parsekeyvaluepair
|
||||
{
|
||||
=pod
|
||||
|
||||
=head2 Escaping special characters
|
||||
|
||||
Key and value strings may be enclosed in quotes, in which case
|
||||
whitespace inside the quotes is preserved. Additionally, an equal
|
||||
sign may be included in the key by preceeding it with a backslash.
|
||||
For example:
|
||||
|
||||
"key1 "=value1
|
||||
key2=" value2"
|
||||
key\=3=value3
|
||||
key4=value=4
|
||||
"key5""=value5
|
||||
|
||||
Here the first key is "key1 " (note the trailing white-space) and the
|
||||
second value is " value2" (note the leading white-space). The third
|
||||
key contains an equal sign "key=3" and so does the fourth value, which
|
||||
does not need to be escaped. The fifth key contains a trailing quote,
|
||||
which does not need to be escaped since it is inside a surrounding
|
||||
quote.
|
||||
|
||||
=cut
|
||||
my $pair = shift;
|
||||
|
||||
# Separate key and value by the first non-quoted equal sign
|
||||
my ($key, $value);
|
||||
if ($pair =~ /^(.*[^\\])=(.*)$/)
|
||||
{
|
||||
($key, $value) = ($1, $2)
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Parse error: $pair\n ";
|
||||
}
|
||||
|
||||
# Unquote and unescape the key and value separately
|
||||
return (&unescape($key), &unescape($value));
|
||||
}
|
||||
|
||||
# Unquote and unescape
|
||||
sub unescape
|
||||
{
|
||||
my $string = shift;
|
||||
|
||||
# First remove enclosing quotes. Backslash before the trailing
|
||||
# quote leaves both.
|
||||
if ($string =~ /^"(.*[^\\])"$/)
|
||||
{
|
||||
$string = $1;
|
||||
}
|
||||
|
||||
# Second remove any backslashes inside the unquoted string.
|
||||
# For later: Handle special sequences like \t ?
|
||||
$string =~ s/\\(.)/$1/g;
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
B<import-directories.perl> F<project.import>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright 2008-2009 Peter Krefting E<lt>peter@softwolves.pp.se>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation.
|
||||
|
||||
=cut
|
||||
@@ -8,9 +8,20 @@
|
||||
## perl import-tars.perl *.tar.bz2
|
||||
## git whatchanged import-tars
|
||||
##
|
||||
## Use --metainfo to specify the extension for a meta data file, where
|
||||
## import-tars can read the commit message and optionally author and
|
||||
## committer information.
|
||||
##
|
||||
## echo 'This is the commit message' > myfile.tar.bz2.msg
|
||||
## perl import-tars.perl --metainfo=msg myfile.tar.bz2
|
||||
|
||||
use strict;
|
||||
die "usage: import-tars *.tar.{gz,bz2,Z}\n" unless @ARGV;
|
||||
use Getopt::Long;
|
||||
|
||||
my $metaext = '';
|
||||
|
||||
die "usage: import-tars [--metainfo=extension] *.tar.{gz,bz2,Z}\n"
|
||||
unless GetOptions('metainfo=s' => \$metaext) && @ARGV;
|
||||
|
||||
my $branch_name = 'import-tars';
|
||||
my $branch_ref = "refs/heads/$branch_name";
|
||||
@@ -109,12 +120,43 @@ foreach my $tar_file (@ARGV)
|
||||
$have_top_dir = 0 if $top_dir ne $1;
|
||||
}
|
||||
|
||||
my $commit_msg = "Imported from $tar_file.";
|
||||
my $this_committer_name = $committer_name;
|
||||
my $this_committer_email = $committer_email;
|
||||
my $this_author_name = $author_name;
|
||||
my $this_author_email = $author_email;
|
||||
if ($metaext ne '') {
|
||||
# Optionally read a commit message from <filename.tar>.msg
|
||||
# Add a line on the form "Committer: name <e-mail>" to override
|
||||
# the committer and "Author: name <e-mail>" to override the
|
||||
# author for this tar ball.
|
||||
if (open MSG, '<', "${tar_file}.${metaext}") {
|
||||
my $header_done = 0;
|
||||
$commit_msg = '';
|
||||
while (<MSG>) {
|
||||
if (!$header_done && /^Committer:\s+([^<>]*)\s+<(.*)>\s*$/i) {
|
||||
$this_committer_name = $1;
|
||||
$this_committer_email = $2;
|
||||
} elsif (!$header_done && /^Author:\s+([^<>]*)\s+<(.*)>\s*$/i) {
|
||||
$this_author_name = $1;
|
||||
$this_author_email = $2;
|
||||
} elsif (!$header_done && /^$/ { # empty line ends header.
|
||||
$header_done = 1;
|
||||
} else {
|
||||
$commit_msg .= $_;
|
||||
$header_done = 1;
|
||||
}
|
||||
}
|
||||
close MSG;
|
||||
}
|
||||
}
|
||||
|
||||
print FI <<EOF;
|
||||
commit $branch_ref
|
||||
author $author_name <$author_email> $author_time +0000
|
||||
committer $committer_name <$committer_email> $commit_time +0000
|
||||
author $this_author_name <$this_author_email> $author_time +0000
|
||||
committer $this_committer_name <$this_committer_email> $commit_time +0000
|
||||
data <<END_OF_COMMIT_MESSAGE
|
||||
Imported from $tar_file.
|
||||
$commit_msg
|
||||
END_OF_COMMIT_MESSAGE
|
||||
|
||||
deleteall
|
||||
|
||||
21
copy.c
21
copy.c
@@ -35,6 +35,19 @@ int copy_fd(int ifd, int ofd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_times(const char *dst, const char *src)
|
||||
{
|
||||
struct stat st;
|
||||
struct utimbuf times;
|
||||
if (stat(src, &st) < 0)
|
||||
return -1;
|
||||
times.actime = st.st_atime;
|
||||
times.modtime = st.st_mtime;
|
||||
if (utime(dst, ×) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int copy_file(const char *dst, const char *src, int mode)
|
||||
{
|
||||
int fdi, fdo, status;
|
||||
@@ -55,3 +68,11 @@ int copy_file(const char *dst, const char *src, int mode)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int copy_file_with_time(const char *dst, const char *src, int mode)
|
||||
{
|
||||
int status = copy_file(dst, src, mode);
|
||||
if (!status)
|
||||
return copy_times(dst, src);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ fi
|
||||
# The tree must be really really clean.
|
||||
if ! git update-index --ignore-submodules --refresh > /dev/null; then
|
||||
echo >&2 "cannot rebase: you have unstaged changes"
|
||||
git diff --name-status -r --ignore-submodules -- >&2
|
||||
git diff-files --name-status -r --ignore-submodules -- >&2
|
||||
exit 1
|
||||
fi
|
||||
diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --)
|
||||
|
||||
@@ -2836,6 +2836,7 @@ sub other_gs {
|
||||
|
||||
sub call_authors_prog {
|
||||
my ($orig_author) = @_;
|
||||
$orig_author = command_oneline('rev-parse', '--sq-quote', $orig_author);
|
||||
my $author = `$::_authors_prog $orig_author`;
|
||||
if ($? != 0) {
|
||||
die "$::_authors_prog failed with exit code $?\n"
|
||||
|
||||
8
git.c
8
git.c
@@ -5,7 +5,10 @@
|
||||
#include "run-command.h"
|
||||
|
||||
const char git_usage_string[] =
|
||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
|
||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
|
||||
" [-p|--paginate|--no-pager]\n"
|
||||
" [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
|
||||
" [--help] COMMAND [ARGS]";
|
||||
|
||||
const char git_more_info_string[] =
|
||||
"See 'git help COMMAND' for more information on a specific command.";
|
||||
@@ -309,9 +312,6 @@ static void handle_internal_command(int argc, const char **argv)
|
||||
{ "get-tar-commit-id", cmd_get_tar_commit_id },
|
||||
{ "grep", cmd_grep, RUN_SETUP | USE_PAGER },
|
||||
{ "help", cmd_help },
|
||||
#ifndef NO_CURL
|
||||
{ "http-fetch", cmd_http_fetch, RUN_SETUP },
|
||||
#endif
|
||||
{ "init", cmd_init_db },
|
||||
{ "init-db", cmd_init_db },
|
||||
{ "log", cmd_log, RUN_SETUP | USE_PAGER },
|
||||
|
||||
1
grep.h
1
grep.h
@@ -59,6 +59,7 @@ struct grep_opt {
|
||||
struct grep_pat *pattern_list;
|
||||
struct grep_pat **pattern_tail;
|
||||
struct grep_expr *pattern_expression;
|
||||
const char *prefix;
|
||||
int prefix_length;
|
||||
regex_t regexp;
|
||||
int linenum;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "cache.h"
|
||||
#include "walker.h"
|
||||
|
||||
int cmd_http_fetch(int argc, const char **argv, const char *prefix)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *prefix;
|
||||
struct walker *walker;
|
||||
int commits_on_stdin = 0;
|
||||
int commits;
|
||||
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
|
||||
int get_verbosely = 0;
|
||||
int get_recover = 0;
|
||||
|
||||
prefix = setup_git_directory();
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
while (arg < argc && argv[arg][0] == '-') {
|
||||
11
http.c
11
http.c
@@ -869,17 +869,6 @@ static int fetch_pack_index(unsigned char *sha1, const char *base_url)
|
||||
char *url;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
/* Don't use the index if the pack isn't there */
|
||||
end_url_with_slash(&buf, base_url);
|
||||
strbuf_addf(&buf, "objects/pack/pack-%s.pack", hex);
|
||||
url = strbuf_detach(&buf, 0);
|
||||
|
||||
if (http_get_strbuf(url, NULL, 0)) {
|
||||
ret = error("Unable to verify pack %s is available",
|
||||
hex);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (has_pack_index(sha1)) {
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
@@ -170,6 +170,18 @@ static int git_merge_trees(int index_only,
|
||||
int rc;
|
||||
struct tree_desc t[3];
|
||||
struct unpack_trees_options opts;
|
||||
static const struct unpack_trees_error_msgs msgs = {
|
||||
/* would_overwrite */
|
||||
"Your local changes to '%s' would be overwritten by merge. Aborting.",
|
||||
/* not_uptodate_file */
|
||||
"Your local changes to '%s' would be overwritten by merge. Aborting.",
|
||||
/* not_uptodate_dir */
|
||||
"Updating '%s' would lose untracked files in it. Aborting.",
|
||||
/* would_lose_untracked */
|
||||
"Untracked working tree file '%s' would be %s by merge. Aborting",
|
||||
/* bind_overlap -- will not happen here */
|
||||
NULL,
|
||||
};
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
if (index_only)
|
||||
@@ -181,6 +193,7 @@ static int git_merge_trees(int index_only,
|
||||
opts.fn = threeway_merge;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
opts.msgs = msgs;
|
||||
|
||||
init_tree_desc_from_tree(t+0, common);
|
||||
init_tree_desc_from_tree(t+1, head);
|
||||
@@ -1188,10 +1201,14 @@ int merge_trees(struct merge_options *o,
|
||||
|
||||
code = git_merge_trees(o->call_depth, common, head, merge);
|
||||
|
||||
if (code != 0)
|
||||
die("merging of trees %s and %s failed",
|
||||
sha1_to_hex(head->object.sha1),
|
||||
sha1_to_hex(merge->object.sha1));
|
||||
if (code != 0) {
|
||||
if (show(o, 4) || o->call_depth)
|
||||
die("merging of trees %s and %s failed",
|
||||
sha1_to_hex(head->object.sha1),
|
||||
sha1_to_hex(merge->object.sha1));
|
||||
else
|
||||
exit(128);
|
||||
}
|
||||
|
||||
if (unmerged_cache()) {
|
||||
struct string_list *entries, *re_head, *re_merge;
|
||||
|
||||
6
pager.c
6
pager.c
@@ -21,8 +21,6 @@ static void pager_preexec(void)
|
||||
FD_ZERO(&in);
|
||||
FD_SET(0, &in);
|
||||
select(1, &in, NULL, &in, NULL);
|
||||
|
||||
setenv("LESS", "FRSX", 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -70,6 +68,10 @@ void setup_pager(void)
|
||||
pager_argv[2] = pager;
|
||||
pager_process.argv = pager_argv;
|
||||
pager_process.in = -1;
|
||||
if (!getenv("LESS")) {
|
||||
static const char *env[] = { "LESS=FRSX", NULL };
|
||||
pager_process.env = env;
|
||||
}
|
||||
#ifndef __MINGW32__
|
||||
pager_process.preexec_cb = pager_preexec;
|
||||
#endif
|
||||
|
||||
139
remote-curl.c
Normal file
139
remote-curl.c
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "cache.h"
|
||||
#include "remote.h"
|
||||
#include "strbuf.h"
|
||||
#include "walker.h"
|
||||
#include "http.h"
|
||||
|
||||
static struct ref *get_refs(struct walker *walker, const char *url)
|
||||
{
|
||||
struct strbuf buffer = STRBUF_INIT;
|
||||
char *data, *start, *mid;
|
||||
char *ref_name;
|
||||
char *refs_url;
|
||||
int i = 0;
|
||||
int http_ret;
|
||||
|
||||
struct ref *refs = NULL;
|
||||
struct ref *ref = NULL;
|
||||
struct ref *last_ref = NULL;
|
||||
|
||||
refs_url = xmalloc(strlen(url) + 11);
|
||||
sprintf(refs_url, "%s/info/refs", url);
|
||||
|
||||
http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
|
||||
switch (http_ret) {
|
||||
case HTTP_OK:
|
||||
break;
|
||||
case HTTP_MISSING_TARGET:
|
||||
die("%s not found: did you run git update-server-info on the"
|
||||
" server?", refs_url);
|
||||
default:
|
||||
http_error(refs_url, http_ret);
|
||||
die("HTTP request failed");
|
||||
}
|
||||
|
||||
data = buffer.buf;
|
||||
start = NULL;
|
||||
mid = data;
|
||||
while (i < buffer.len) {
|
||||
if (!start) {
|
||||
start = &data[i];
|
||||
}
|
||||
if (data[i] == '\t')
|
||||
mid = &data[i];
|
||||
if (data[i] == '\n') {
|
||||
data[i] = 0;
|
||||
ref_name = mid + 1;
|
||||
ref = xmalloc(sizeof(struct ref) +
|
||||
strlen(ref_name) + 1);
|
||||
memset(ref, 0, sizeof(struct ref));
|
||||
strcpy(ref->name, ref_name);
|
||||
get_sha1_hex(start, ref->old_sha1);
|
||||
if (!refs)
|
||||
refs = ref;
|
||||
if (last_ref)
|
||||
last_ref->next = ref;
|
||||
last_ref = ref;
|
||||
start = NULL;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
strbuf_release(&buffer);
|
||||
|
||||
ref = alloc_ref("HEAD");
|
||||
if (!walker->fetch_ref(walker, ref) &&
|
||||
!resolve_remote_symref(ref, refs)) {
|
||||
ref->next = refs;
|
||||
refs = ref;
|
||||
} else {
|
||||
free(ref);
|
||||
}
|
||||
|
||||
strbuf_release(&buffer);
|
||||
free(refs_url);
|
||||
return refs;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct remote *remote;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
const char *url;
|
||||
struct walker *walker = NULL;
|
||||
|
||||
setup_git_directory();
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Remote needed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
remote = remote_get(argv[1]);
|
||||
|
||||
if (argc > 2) {
|
||||
url = argv[2];
|
||||
} else {
|
||||
url = remote->url[0];
|
||||
}
|
||||
|
||||
do {
|
||||
if (strbuf_getline(&buf, stdin, '\n') == EOF)
|
||||
break;
|
||||
if (!prefixcmp(buf.buf, "fetch ")) {
|
||||
char *obj = buf.buf + strlen("fetch ");
|
||||
if (!walker)
|
||||
walker = get_http_walker(url, remote);
|
||||
walker->get_all = 1;
|
||||
walker->get_tree = 1;
|
||||
walker->get_history = 1;
|
||||
walker->get_verbosely = 0;
|
||||
walker->get_recover = 0;
|
||||
if (walker_fetch(walker, 1, &obj, NULL, NULL))
|
||||
die("Fetch failed.");
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
} else if (!strcmp(buf.buf, "list")) {
|
||||
struct ref *refs;
|
||||
struct ref *posn;
|
||||
if (!walker)
|
||||
walker = get_http_walker(url, remote);
|
||||
refs = get_refs(walker, url);
|
||||
for (posn = refs; posn; posn = posn->next) {
|
||||
if (posn->symref)
|
||||
printf("@%s %s\n", posn->symref, posn->name);
|
||||
else
|
||||
printf("%s %s\n", sha1_to_hex(posn->old_sha1), posn->name);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
} else if (!strcmp(buf.buf, "capabilities")) {
|
||||
printf("fetch\n");
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
strbuf_reset(&buf);
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
83
remote.c
83
remote.c
@@ -28,6 +28,11 @@ struct rewrite {
|
||||
int instead_of_nr;
|
||||
int instead_of_alloc;
|
||||
};
|
||||
struct rewrites {
|
||||
struct rewrite **rewrite;
|
||||
int rewrite_alloc;
|
||||
int rewrite_nr;
|
||||
};
|
||||
|
||||
static struct remote **remotes;
|
||||
static int remotes_alloc;
|
||||
@@ -41,14 +46,13 @@ static struct branch *current_branch;
|
||||
static const char *default_remote_name;
|
||||
static int explicit_default_remote_name;
|
||||
|
||||
static struct rewrite **rewrite;
|
||||
static int rewrite_alloc;
|
||||
static int rewrite_nr;
|
||||
static struct rewrites rewrites;
|
||||
static struct rewrites rewrites_push;
|
||||
|
||||
#define BUF_SIZE (2048)
|
||||
static char buffer[BUF_SIZE];
|
||||
|
||||
static const char *alias_url(const char *url)
|
||||
static const char *alias_url(const char *url, struct rewrites *r)
|
||||
{
|
||||
int i, j;
|
||||
char *ret;
|
||||
@@ -57,14 +61,14 @@ static const char *alias_url(const char *url)
|
||||
|
||||
longest = NULL;
|
||||
longest_i = -1;
|
||||
for (i = 0; i < rewrite_nr; i++) {
|
||||
if (!rewrite[i])
|
||||
for (i = 0; i < r->rewrite_nr; i++) {
|
||||
if (!r->rewrite[i])
|
||||
continue;
|
||||
for (j = 0; j < rewrite[i]->instead_of_nr; j++) {
|
||||
if (!prefixcmp(url, rewrite[i]->instead_of[j].s) &&
|
||||
for (j = 0; j < r->rewrite[i]->instead_of_nr; j++) {
|
||||
if (!prefixcmp(url, r->rewrite[i]->instead_of[j].s) &&
|
||||
(!longest ||
|
||||
longest->len < rewrite[i]->instead_of[j].len)) {
|
||||
longest = &(rewrite[i]->instead_of[j]);
|
||||
longest->len < r->rewrite[i]->instead_of[j].len)) {
|
||||
longest = &(r->rewrite[i]->instead_of[j]);
|
||||
longest_i = i;
|
||||
}
|
||||
}
|
||||
@@ -72,10 +76,10 @@ static const char *alias_url(const char *url)
|
||||
if (!longest)
|
||||
return url;
|
||||
|
||||
ret = xmalloc(rewrite[longest_i]->baselen +
|
||||
ret = xmalloc(r->rewrite[longest_i]->baselen +
|
||||
(strlen(url) - longest->len) + 1);
|
||||
strcpy(ret, rewrite[longest_i]->base);
|
||||
strcpy(ret + rewrite[longest_i]->baselen, url + longest->len);
|
||||
strcpy(ret, r->rewrite[longest_i]->base);
|
||||
strcpy(ret + r->rewrite[longest_i]->baselen, url + longest->len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -101,17 +105,25 @@ static void add_url(struct remote *remote, const char *url)
|
||||
remote->url[remote->url_nr++] = url;
|
||||
}
|
||||
|
||||
static void add_url_alias(struct remote *remote, const char *url)
|
||||
{
|
||||
add_url(remote, alias_url(url));
|
||||
}
|
||||
|
||||
static void add_pushurl(struct remote *remote, const char *pushurl)
|
||||
{
|
||||
ALLOC_GROW(remote->pushurl, remote->pushurl_nr + 1, remote->pushurl_alloc);
|
||||
remote->pushurl[remote->pushurl_nr++] = pushurl;
|
||||
}
|
||||
|
||||
static void add_pushurl_alias(struct remote *remote, const char *url)
|
||||
{
|
||||
const char *pushurl = alias_url(url, &rewrites_push);
|
||||
if (pushurl != url)
|
||||
add_pushurl(remote, pushurl);
|
||||
}
|
||||
|
||||
static void add_url_alias(struct remote *remote, const char *url)
|
||||
{
|
||||
add_url(remote, alias_url(url, &rewrites));
|
||||
add_pushurl_alias(remote, url);
|
||||
}
|
||||
|
||||
static struct remote *make_remote(const char *name, int len)
|
||||
{
|
||||
struct remote *ret;
|
||||
@@ -169,22 +181,22 @@ static struct branch *make_branch(const char *name, int len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct rewrite *make_rewrite(const char *base, int len)
|
||||
static struct rewrite *make_rewrite(struct rewrites *r, const char *base, int len)
|
||||
{
|
||||
struct rewrite *ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rewrite_nr; i++) {
|
||||
for (i = 0; i < r->rewrite_nr; i++) {
|
||||
if (len
|
||||
? (len == rewrite[i]->baselen &&
|
||||
!strncmp(base, rewrite[i]->base, len))
|
||||
: !strcmp(base, rewrite[i]->base))
|
||||
return rewrite[i];
|
||||
? (len == r->rewrite[i]->baselen &&
|
||||
!strncmp(base, r->rewrite[i]->base, len))
|
||||
: !strcmp(base, r->rewrite[i]->base))
|
||||
return r->rewrite[i];
|
||||
}
|
||||
|
||||
ALLOC_GROW(rewrite, rewrite_nr + 1, rewrite_alloc);
|
||||
ALLOC_GROW(r->rewrite, r->rewrite_nr + 1, r->rewrite_alloc);
|
||||
ret = xcalloc(1, sizeof(struct rewrite));
|
||||
rewrite[rewrite_nr++] = ret;
|
||||
r->rewrite[r->rewrite_nr++] = ret;
|
||||
if (len) {
|
||||
ret->base = xstrndup(base, len);
|
||||
ret->baselen = len;
|
||||
@@ -355,8 +367,13 @@ static int handle_config(const char *key, const char *value, void *cb)
|
||||
subkey = strrchr(name, '.');
|
||||
if (!subkey)
|
||||
return 0;
|
||||
rewrite = make_rewrite(name, subkey - name);
|
||||
if (!strcmp(subkey, ".insteadof")) {
|
||||
rewrite = make_rewrite(&rewrites, name, subkey - name);
|
||||
if (!value)
|
||||
return config_error_nonbool(key);
|
||||
add_instead_of(rewrite, xstrdup(value));
|
||||
} else if (!strcmp(subkey, ".pushinsteadof")) {
|
||||
rewrite = make_rewrite(&rewrites_push, name, subkey - name);
|
||||
if (!value)
|
||||
return config_error_nonbool(key);
|
||||
add_instead_of(rewrite, xstrdup(value));
|
||||
@@ -430,13 +447,17 @@ static void alias_all_urls(void)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < remotes_nr; i++) {
|
||||
int add_pushurl_aliases;
|
||||
if (!remotes[i])
|
||||
continue;
|
||||
for (j = 0; j < remotes[i]->url_nr; j++) {
|
||||
remotes[i]->url[j] = alias_url(remotes[i]->url[j]);
|
||||
}
|
||||
for (j = 0; j < remotes[i]->pushurl_nr; j++) {
|
||||
remotes[i]->pushurl[j] = alias_url(remotes[i]->pushurl[j]);
|
||||
remotes[i]->pushurl[j] = alias_url(remotes[i]->pushurl[j], &rewrites);
|
||||
}
|
||||
add_pushurl_aliases = remotes[i]->pushurl_nr == 0;
|
||||
for (j = 0; j < remotes[i]->url_nr; j++) {
|
||||
if (add_pushurl_aliases)
|
||||
add_pushurl_alias(remotes[i], remotes[i]->url[j]);
|
||||
remotes[i]->url[j] = alias_url(remotes[i]->url[j], &rewrites);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
rerere.c
2
rerere.c
@@ -61,7 +61,7 @@ static int write_rr(struct string_list *rr, int out_fd)
|
||||
path = rr->items[i].string;
|
||||
length = strlen(path) + 1;
|
||||
if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
|
||||
write_in_full(out_fd, "\t", 1) != 1 ||
|
||||
write_str_in_full(out_fd, "\t") != 1 ||
|
||||
write_in_full(out_fd, path, length) != length)
|
||||
die("unable to write rerere record");
|
||||
}
|
||||
|
||||
@@ -173,11 +173,8 @@ fail_pipe:
|
||||
|
||||
if (cmd->dir)
|
||||
die("chdir in start_command() not implemented");
|
||||
if (cmd->env) {
|
||||
env = copy_environ();
|
||||
for (; *cmd->env; cmd->env++)
|
||||
env = env_setenv(env, *cmd->env);
|
||||
}
|
||||
if (cmd->env)
|
||||
env = make_augmented_environ(cmd->env);
|
||||
|
||||
if (cmd->git_cmd) {
|
||||
cmd->argv = prepare_git_cmd(cmd->argv);
|
||||
|
||||
@@ -122,6 +122,23 @@ test_expect_success 'fetch with insteadOf' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'fetch with pushInsteadOf (should not rewrite)' '
|
||||
mk_empty &&
|
||||
(
|
||||
TRASH=$(pwd)/ &&
|
||||
cd testrepo &&
|
||||
git config "url.trash/.pushInsteadOf" "$TRASH" &&
|
||||
git config remote.up.url "$TRASH." &&
|
||||
git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
|
||||
git fetch up &&
|
||||
|
||||
r=$(git show-ref -s --verify refs/remotes/origin/master) &&
|
||||
test "z$r" = "z$the_commit" &&
|
||||
|
||||
test 1 = $(git for-each-ref refs/remotes/origin | wc -l)
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'push without wildcard' '
|
||||
mk_empty &&
|
||||
|
||||
@@ -162,6 +179,36 @@ test_expect_success 'push with insteadOf' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'push with pushInsteadOf' '
|
||||
mk_empty &&
|
||||
TRASH="$(pwd)/" &&
|
||||
git config "url.$TRASH.pushInsteadOf" trash/ &&
|
||||
git push trash/testrepo refs/heads/master:refs/remotes/origin/master &&
|
||||
(
|
||||
cd testrepo &&
|
||||
r=$(git show-ref -s --verify refs/remotes/origin/master) &&
|
||||
test "z$r" = "z$the_commit" &&
|
||||
|
||||
test 1 = $(git for-each-ref refs/remotes/origin | wc -l)
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' '
|
||||
mk_empty &&
|
||||
TRASH="$(pwd)/" &&
|
||||
git config "url.trash2/.pushInsteadOf" trash/ &&
|
||||
git config remote.r.url trash/wrong &&
|
||||
git config remote.r.pushurl "$TRASH/testrepo" &&
|
||||
git push r refs/heads/master:refs/remotes/origin/master &&
|
||||
(
|
||||
cd testrepo &&
|
||||
r=$(git show-ref -s --verify refs/remotes/origin/master) &&
|
||||
test "z$r" = "z$the_commit" &&
|
||||
|
||||
test 1 = $(git for-each-ref refs/remotes/origin | wc -l)
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'push with matching heads' '
|
||||
|
||||
mk_test heads/master &&
|
||||
|
||||
@@ -328,4 +328,21 @@ test_expect_success 'grep -p -B5' '
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'grep from a subdirectory to search wider area (1)' '
|
||||
mkdir -p s &&
|
||||
(
|
||||
cd s && git grep "x x x" ..
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'grep from a subdirectory to search wider area (2)' '
|
||||
mkdir -p s &&
|
||||
(
|
||||
cd s || exit 1
|
||||
( git grep xxyyzz .. >out ; echo $? >status )
|
||||
! test -s out &&
|
||||
test 1 = $(cat status)
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -66,4 +66,18 @@ test_expect_success 'authors-file overrode authors-prog' '
|
||||
)
|
||||
'
|
||||
|
||||
git --git-dir=x/.git config --unset svn.authorsfile
|
||||
git --git-dir=x/.git config --unset svn.authorsprog
|
||||
|
||||
test_expect_success 'authors-prog handled special characters in username' '
|
||||
svn mkdir -m bad --username "xyz; touch evil" "$svnrepo"/bad &&
|
||||
(
|
||||
cd x &&
|
||||
git svn --authors-prog=../svn-authors-prog fetch &&
|
||||
git rev-list -1 --pretty=raw refs/remotes/git-svn |
|
||||
grep "^author xyz; touch evil <xyz; touch evil@example\.com> " &&
|
||||
! test -f evil
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
168
transport-helper.c
Normal file
168
transport-helper.c
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "cache.h"
|
||||
#include "transport.h"
|
||||
|
||||
#include "run-command.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
|
||||
struct helper_data
|
||||
{
|
||||
const char *name;
|
||||
struct child_process *helper;
|
||||
unsigned fetch : 1;
|
||||
};
|
||||
|
||||
static struct child_process *get_helper(struct transport *transport)
|
||||
{
|
||||
struct helper_data *data = transport->data;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct child_process *helper;
|
||||
FILE *file;
|
||||
|
||||
if (data->helper)
|
||||
return data->helper;
|
||||
|
||||
helper = xcalloc(1, sizeof(*helper));
|
||||
helper->in = -1;
|
||||
helper->out = -1;
|
||||
helper->err = 0;
|
||||
helper->argv = xcalloc(4, sizeof(*helper->argv));
|
||||
strbuf_addf(&buf, "remote-%s", data->name);
|
||||
helper->argv[0] = strbuf_detach(&buf, NULL);
|
||||
helper->argv[1] = transport->remote->name;
|
||||
helper->argv[2] = transport->url;
|
||||
helper->git_cmd = 1;
|
||||
if (start_command(helper))
|
||||
die("Unable to run helper: git %s", helper->argv[0]);
|
||||
data->helper = helper;
|
||||
|
||||
write_str_in_full(helper->in, "capabilities\n");
|
||||
|
||||
file = xfdopen(helper->out, "r");
|
||||
while (1) {
|
||||
if (strbuf_getline(&buf, file, '\n') == EOF)
|
||||
exit(128); /* child died, message supplied already */
|
||||
|
||||
if (!*buf.buf)
|
||||
break;
|
||||
if (!strcmp(buf.buf, "fetch"))
|
||||
data->fetch = 1;
|
||||
}
|
||||
return data->helper;
|
||||
}
|
||||
|
||||
static int disconnect_helper(struct transport *transport)
|
||||
{
|
||||
struct helper_data *data = transport->data;
|
||||
if (data->helper) {
|
||||
write_str_in_full(data->helper->in, "\n");
|
||||
close(data->helper->in);
|
||||
finish_command(data->helper);
|
||||
free((char *)data->helper->argv[0]);
|
||||
free(data->helper->argv);
|
||||
free(data->helper);
|
||||
data->helper = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fetch_with_fetch(struct transport *transport,
|
||||
int nr_heads, const struct ref **to_fetch)
|
||||
{
|
||||
struct child_process *helper = get_helper(transport);
|
||||
FILE *file = xfdopen(helper->out, "r");
|
||||
int i;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
for (i = 0; i < nr_heads; i++) {
|
||||
const struct ref *posn = to_fetch[i];
|
||||
if (posn->status & REF_STATUS_UPTODATE)
|
||||
continue;
|
||||
|
||||
strbuf_addf(&buf, "fetch %s %s\n",
|
||||
sha1_to_hex(posn->old_sha1), posn->name);
|
||||
write_in_full(helper->in, buf.buf, buf.len);
|
||||
strbuf_reset(&buf);
|
||||
|
||||
if (strbuf_getline(&buf, file, '\n') == EOF)
|
||||
exit(128); /* child died, message supplied already */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fetch(struct transport *transport,
|
||||
int nr_heads, const struct ref **to_fetch)
|
||||
{
|
||||
struct helper_data *data = transport->data;
|
||||
int i, count;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < nr_heads; i++)
|
||||
if (!(to_fetch[i]->status & REF_STATUS_UPTODATE))
|
||||
count++;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
if (data->fetch)
|
||||
return fetch_with_fetch(transport, nr_heads, to_fetch);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_list(struct transport *transport, int for_push)
|
||||
{
|
||||
struct child_process *helper;
|
||||
struct ref *ret = NULL;
|
||||
struct ref **tail = &ret;
|
||||
struct ref *posn;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
FILE *file;
|
||||
|
||||
helper = get_helper(transport);
|
||||
|
||||
write_str_in_full(helper->in, "list\n");
|
||||
|
||||
file = xfdopen(helper->out, "r");
|
||||
while (1) {
|
||||
char *eov, *eon;
|
||||
if (strbuf_getline(&buf, file, '\n') == EOF)
|
||||
exit(128); /* child died, message supplied already */
|
||||
|
||||
if (!*buf.buf)
|
||||
break;
|
||||
|
||||
eov = strchr(buf.buf, ' ');
|
||||
if (!eov)
|
||||
die("Malformed response in ref list: %s", buf.buf);
|
||||
eon = strchr(eov + 1, ' ');
|
||||
*eov = '\0';
|
||||
if (eon)
|
||||
*eon = '\0';
|
||||
*tail = alloc_ref(eov + 1);
|
||||
if (buf.buf[0] == '@')
|
||||
(*tail)->symref = xstrdup(buf.buf + 1);
|
||||
else if (buf.buf[0] != '?')
|
||||
get_sha1_hex(buf.buf, (*tail)->old_sha1);
|
||||
tail = &((*tail)->next);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
|
||||
for (posn = ret; posn; posn = posn->next)
|
||||
resolve_remote_symref(posn, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int transport_helper_init(struct transport *transport, const char *name)
|
||||
{
|
||||
struct helper_data *data = xcalloc(sizeof(*data), 1);
|
||||
data->name = name;
|
||||
|
||||
transport->data = data;
|
||||
transport->get_refs_list = get_refs_list;
|
||||
transport->fetch = fetch;
|
||||
transport->disconnect = disconnect_helper;
|
||||
return 0;
|
||||
}
|
||||
136
transport.c
136
transport.c
@@ -1,9 +1,6 @@
|
||||
#include "cache.h"
|
||||
#include "transport.h"
|
||||
#include "run-command.h"
|
||||
#ifndef NO_CURL
|
||||
#include "http.h"
|
||||
#endif
|
||||
#include "pkt-line.h"
|
||||
#include "fetch-pack.h"
|
||||
#include "send-pack.h"
|
||||
@@ -352,45 +349,6 @@ static int rsync_transport_push(struct transport *transport,
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Generic functions for using commit walkers */
|
||||
|
||||
#ifndef NO_CURL /* http fetch is the only user */
|
||||
static int fetch_objs_via_walker(struct transport *transport,
|
||||
int nr_objs, const struct ref **to_fetch)
|
||||
{
|
||||
char *dest = xstrdup(transport->url);
|
||||
struct walker *walker = transport->data;
|
||||
char **objs = xmalloc(nr_objs * sizeof(*objs));
|
||||
int i;
|
||||
|
||||
walker->get_all = 1;
|
||||
walker->get_tree = 1;
|
||||
walker->get_history = 1;
|
||||
walker->get_verbosely = transport->verbose >= 0;
|
||||
walker->get_recover = 0;
|
||||
|
||||
for (i = 0; i < nr_objs; i++)
|
||||
objs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));
|
||||
|
||||
if (walker_fetch(walker, nr_objs, objs, NULL, NULL))
|
||||
die("Fetch failed.");
|
||||
|
||||
for (i = 0; i < nr_objs; i++)
|
||||
free(objs[i]);
|
||||
free(objs);
|
||||
free(dest);
|
||||
return 0;
|
||||
}
|
||||
#endif /* NO_CURL */
|
||||
|
||||
static int disconnect_walker(struct transport *transport)
|
||||
{
|
||||
struct walker *walker = transport->data;
|
||||
if (walker)
|
||||
walker_free(walker);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NO_CURL
|
||||
static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
|
||||
{
|
||||
@@ -418,96 +376,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
|
||||
return !!run_command_v_opt(argv, RUN_GIT_CMD);
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
|
||||
{
|
||||
struct strbuf buffer = STRBUF_INIT;
|
||||
char *data, *start, *mid;
|
||||
char *ref_name;
|
||||
char *refs_url;
|
||||
int i = 0;
|
||||
int http_ret;
|
||||
|
||||
struct ref *refs = NULL;
|
||||
struct ref *ref = NULL;
|
||||
struct ref *last_ref = NULL;
|
||||
|
||||
struct walker *walker;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
if (!transport->data)
|
||||
transport->data = get_http_walker(transport->url,
|
||||
transport->remote);
|
||||
|
||||
walker = transport->data;
|
||||
|
||||
refs_url = xmalloc(strlen(transport->url) + 11);
|
||||
sprintf(refs_url, "%s/info/refs", transport->url);
|
||||
|
||||
http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
|
||||
switch (http_ret) {
|
||||
case HTTP_OK:
|
||||
break;
|
||||
case HTTP_MISSING_TARGET:
|
||||
die("%s not found: did you run git update-server-info on the"
|
||||
" server?", refs_url);
|
||||
default:
|
||||
http_error(refs_url, http_ret);
|
||||
die("HTTP request failed");
|
||||
}
|
||||
|
||||
data = buffer.buf;
|
||||
start = NULL;
|
||||
mid = data;
|
||||
while (i < buffer.len) {
|
||||
if (!start)
|
||||
start = &data[i];
|
||||
if (data[i] == '\t')
|
||||
mid = &data[i];
|
||||
if (data[i] == '\n') {
|
||||
data[i] = 0;
|
||||
ref_name = mid + 1;
|
||||
ref = xmalloc(sizeof(struct ref) +
|
||||
strlen(ref_name) + 1);
|
||||
memset(ref, 0, sizeof(struct ref));
|
||||
strcpy(ref->name, ref_name);
|
||||
get_sha1_hex(start, ref->old_sha1);
|
||||
if (!refs)
|
||||
refs = ref;
|
||||
if (last_ref)
|
||||
last_ref->next = ref;
|
||||
last_ref = ref;
|
||||
start = NULL;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
strbuf_release(&buffer);
|
||||
|
||||
ref = alloc_ref("HEAD");
|
||||
if (!walker->fetch_ref(walker, ref) &&
|
||||
!resolve_remote_symref(ref, refs)) {
|
||||
ref->next = refs;
|
||||
refs = ref;
|
||||
} else {
|
||||
free(ref);
|
||||
}
|
||||
|
||||
strbuf_release(&buffer);
|
||||
free(refs_url);
|
||||
return refs;
|
||||
}
|
||||
|
||||
static int fetch_objs_via_curl(struct transport *transport,
|
||||
int nr_objs, const struct ref **to_fetch)
|
||||
{
|
||||
if (!transport->data)
|
||||
transport->data = get_http_walker(transport->url,
|
||||
transport->remote);
|
||||
return fetch_objs_via_walker(transport, nr_objs, to_fetch);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct bundle_transport_data {
|
||||
@@ -955,14 +823,12 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
||||
} else if (!prefixcmp(url, "http://")
|
||||
|| !prefixcmp(url, "https://")
|
||||
|| !prefixcmp(url, "ftp://")) {
|
||||
transport_helper_init(ret, "curl");
|
||||
#ifdef NO_CURL
|
||||
error("git was compiled without libcurl support.");
|
||||
#else
|
||||
ret->get_refs_list = get_refs_via_curl;
|
||||
ret->fetch = fetch_objs_via_curl;
|
||||
ret->push = curl_transport_push;
|
||||
#endif
|
||||
ret->disconnect = disconnect_walker;
|
||||
|
||||
} else if (is_local(url) && is_file(url)) {
|
||||
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
|
||||
|
||||
@@ -79,4 +79,7 @@ void transport_unlock_pack(struct transport *transport);
|
||||
int transport_disconnect(struct transport *transport);
|
||||
char *transport_anonymize_url(const char *url);
|
||||
|
||||
/* Transport methods defined outside transport.c */
|
||||
int transport_helper_init(struct transport *transport, const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -108,7 +108,7 @@ static int do_rev_list(int fd, void *create_full_pack)
|
||||
int i;
|
||||
struct rev_info revs;
|
||||
|
||||
pack_pipe = fdopen(fd, "w");
|
||||
pack_pipe = xfdopen(fd, "w");
|
||||
init_revisions(&revs, NULL);
|
||||
revs.tag_objects = 1;
|
||||
revs.tree_objects = 1;
|
||||
@@ -255,7 +255,7 @@ static void create_pack_file(void)
|
||||
|
||||
/* pass on revisions we (don't) want */
|
||||
if (!shallow_nr) {
|
||||
FILE *pipe_fd = fdopen(pack_objects.in, "w");
|
||||
FILE *pipe_fd = xfdopen(pack_objects.in, "w");
|
||||
if (!create_full_pack) {
|
||||
int i;
|
||||
for (i = 0; i < want_obj.nr; i++)
|
||||
@@ -553,7 +553,7 @@ static void receive_needs(void)
|
||||
|
||||
shallow_nr = 0;
|
||||
if (debug_fd)
|
||||
write_in_full(debug_fd, "#S\n", 3);
|
||||
write_str_in_full(debug_fd, "#S\n");
|
||||
for (;;) {
|
||||
struct object *o;
|
||||
unsigned char sha1_buf[20];
|
||||
@@ -619,7 +619,7 @@ static void receive_needs(void)
|
||||
}
|
||||
}
|
||||
if (debug_fd)
|
||||
write_in_full(debug_fd, "#E\n", 3);
|
||||
write_str_in_full(debug_fd, "#E\n");
|
||||
|
||||
if (!use_sideband && daemon_mode)
|
||||
no_progress = 1;
|
||||
|
||||
@@ -48,6 +48,8 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
|
||||
{
|
||||
const char *c = color(WT_STATUS_HEADER, s);
|
||||
color_fprintf_ln(s->fp, c, "# Unmerged paths:");
|
||||
if (!advice_status_hints)
|
||||
return;
|
||||
if (!s->is_initial)
|
||||
color_fprintf_ln(s->fp, c, "# (use \"git reset %s <file>...\" to unstage)", s->reference);
|
||||
else
|
||||
@@ -60,6 +62,8 @@ static void wt_status_print_cached_header(struct wt_status *s)
|
||||
{
|
||||
const char *c = color(WT_STATUS_HEADER, s);
|
||||
color_fprintf_ln(s->fp, c, "# Changes to be committed:");
|
||||
if (!advice_status_hints)
|
||||
return;
|
||||
if (!s->is_initial) {
|
||||
color_fprintf_ln(s->fp, c, "# (use \"git reset %s <file>...\" to unstage)", s->reference);
|
||||
} else {
|
||||
@@ -73,6 +77,8 @@ static void wt_status_print_dirty_header(struct wt_status *s,
|
||||
{
|
||||
const char *c = color(WT_STATUS_HEADER, s);
|
||||
color_fprintf_ln(s->fp, c, "# Changed but not updated:");
|
||||
if (!advice_status_hints)
|
||||
return;
|
||||
if (!has_deleted)
|
||||
color_fprintf_ln(s->fp, c, "# (use \"git add <file>...\" to update what will be committed)");
|
||||
else
|
||||
@@ -85,6 +91,8 @@ static void wt_status_print_untracked_header(struct wt_status *s)
|
||||
{
|
||||
const char *c = color(WT_STATUS_HEADER, s);
|
||||
color_fprintf_ln(s->fp, c, "# Untracked files:");
|
||||
if (!advice_status_hints)
|
||||
return;
|
||||
color_fprintf_ln(s->fp, c, "# (use \"git add <file>...\" to include in what will be committed)");
|
||||
color_fprintf_ln(s->fp, c, "#");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user