Merge branch 'master' of git://repo.or.cz/alt-git

This commit is contained in:
Johannes Sixt
2009-09-14 09:06:29 +02:00
55 changed files with 1321 additions and 296 deletions

1
.gitignore vendored
View File

@@ -104,6 +104,7 @@ git-receive-pack
git-reflog
git-relink
git-remote
git-remote-curl
git-repack
git-replace
git-repo-config

View 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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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].

View File

@@ -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
View File

@@ -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

View File

@@ -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
View 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
View 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 */

View File

@@ -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");

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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.

View File

@@ -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");

View File

@@ -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);

View File

@@ -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
View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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];

View File

@@ -1532,7 +1532,7 @@ _git_config ()
url.*.*)
local pfx="${cur%.*}."
cur="${cur##*.}"
__gitcomp "insteadof" "$pfx" "$cur"
__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur"
return
;;
esac

View File

@@ -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]

View File

@@ -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))

View 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

View File

@@ -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
View File

@@ -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, &times) < 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;
}

View File

@@ -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 --)

View File

@@ -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
View File

@@ -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
View File

@@ -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;

View File

@@ -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
View File

@@ -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;

View File

@@ -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;

View File

@@ -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
View 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;
}

View File

@@ -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);
}
}
}

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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 &&

View File

@@ -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

View File

@@ -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
View 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;
}

View File

@@ -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));

View File

@@ -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

View File

@@ -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;

View File

@@ -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, "#");
}