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

This commit is contained in:
Johannes Sixt
2010-02-01 07:44:29 +01:00
88 changed files with 5223 additions and 1257 deletions

1
.gitignore vendored
View File

@@ -166,6 +166,7 @@
/test-match-trees
/test-parse-options
/test-path-utils
/test-run-command
/test-sha1
/test-sigchain
/common-cmds.h

View File

@@ -25,7 +25,7 @@ Notes on behaviour change
configured that variable.
* "git status" is not "git commit --dry-run" anymore. This change does
not affect you if you run the command without pathspec.
not affect you if you run the command without argument.
* "git diff" traditionally treated various "ignore whitespace" options
only as a way to filter the patch output. "git diff --exit-code -b"
@@ -38,6 +38,13 @@ Notes on behaviour change
whitespaces is reported with zero exit status when run with
--exit-code, and there is no "diff --git" header for such a change.
* external diff and textconv helpers are now executed using the shell.
This makes them consistent with other programs executed by git, and
allows you to pass command-line parameters to the helpers. Any helper
paths containing spaces or other metacharacters now need to be
shell-quoted. The affected helpers are GIT_EXTERNAL_DIFF in the
environment, and diff.*.command and diff.*.textconv in the config
file.
Updates since v1.6.6
--------------------
@@ -48,6 +55,10 @@ Updates since v1.6.6
mismatch between fast-import and the frontends that produce the input
stream.
* "git svn" support of subversion "merge tickets" and miscellaneous fixes.
* "gitk" updates.
(portability)
* Some more MSVC portability patches for msysgit port.
@@ -113,11 +124,14 @@ Updates since v1.6.6
* "git fetch --all" can now be used in place of "git remote update".
* "git grep" does not rely on external grep anymore.
* "git grep" does not rely on external grep anymore. It can use more than
one threads to accelerate the operation.
* "git grep" learned "--no-index" option, to search inside contents that
are not managed by git.
* "git grep" learned "--quiet" option.
* "git log" and friends learned "--glob=heads/*" syntax that is a more
flexible way to complement "--branches/--tags/--remotes".
@@ -168,6 +182,9 @@ Updates since v1.6.6
* Many more commands are now built-in.
* THREADED_DELTA_SEARCH is no more. If you build with threads, delta
compression will always take advantage of it.
Fixes since v1.6.6
------------------
@@ -178,6 +195,11 @@ release, unless otherwise noted.
the branch is fully merged to its upstream branch if it is not merged
to the current branch. It now deletes it in such a case.
* "git config -f <relative path>" run from a subdirectory misbehaved.
65807ee (builtin-config: Fix crash when using "-f <relative path>"
from non-root dir, 2010-01-26) may be merged to older maintenance
branches.
* When "git diff" is asked to compare the work tree with something,
it used to consider that a checked-out submodule with uncommitted
changes is not modified; this could cause people to forget committing
@@ -186,6 +208,6 @@ release, unless otherwise noted.
--
exec >/var/tmp/1
O=v1.6.6.1-434-g3521c1b
O=v1.7.0-rc1-6-g2ee8c5b
echo O=$(git describe master)
git shortlog --no-merges $O..master ^maint

View File

@@ -19,7 +19,7 @@ git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]::
git-diff-files [<pattern>...]::
compares the index and the files on the filesystem.
The "git-diff-tree" command begins its ouput by printing the hash of
The "git-diff-tree" command begins its output by printing the hash of
what is being compared. After that, all the commands print one output
line per changed file.

View File

@@ -799,7 +799,7 @@ fixed in the "main" branch by commit "F"?
The result of such a bisection would be that we would find that H is
the first bad commit, when in fact it's B. So that would be wrong!
And yes it's can happen in practice that people working on one branch
And yes it can happen in practice that people working on one branch
are not aware that people working on another branch fixed a bug! It
could also happen that F fixed more than one bug or that it is a
revert of some big development effort that was not ready to be

View File

@@ -37,7 +37,7 @@ unsigned, with 'verbatim', they will be silently exported
and with 'warn', they will be exported, but you will see a warning.
--tag-of-filtered-object=(abort|drop|rewrite)::
Specify how to handle tags whose tagged objectis filtered out.
Specify how to handle tags whose tagged object is filtered out.
Since revisions and files to export can be limited by path,
tagged objects may be filtered completely.
+

View File

@@ -152,7 +152,7 @@ fast-forward update, fast-import will skip updating that ref and instead
prints a warning message. fast-import will always attempt to update all
branch refs, and does not stop on the first failure.
Branch updates can be forced with \--force, but its recommended that
Branch updates can be forced with \--force, but it's recommended that
this only be used on an otherwise quiet repository. Using \--force
is not necessary for an initial import into an empty repository.
@@ -267,7 +267,7 @@ is always copied into the identity string at the time it is being
created by fast-import. There is no way to specify a different time or
timezone.
+
This particular format is supplied as its short to implement and
This particular format is supplied as it's short to implement and
may be useful to a process that wants to create a new commit
right now, without needing to use a working directory or
'git update-index'.
@@ -420,7 +420,7 @@ quoting or escaping syntax is supported within `<committish>`.
Here `<committish>` is any of the following:
* The name of an existing branch already in fast-import's internal branch
table. If fast-import doesn't know the name, its treated as a SHA-1
table. If fast-import doesn't know the name, it's treated as a SHA-1
expression.
* A mark reference, `:<idnum>`, where `<idnum>` is the mark number.
@@ -759,7 +759,7 @@ assigned mark.
The mark command is optional here as some frontends have chosen
to generate the Git SHA-1 for the blob on their own, and feed that
directly to `commit`. This is typically more work than its worth
directly to `commit`. This is typically more work than it's worth
however, as marks are inexpensive to store and easy to use.
`data`

View File

@@ -16,7 +16,7 @@ SYNOPSIS
[-F | --fixed-strings] [-n]
[-l | --files-with-matches] [-L | --files-without-match]
[-z | --null]
[-c | --count] [--all-match]
[-c | --count] [--all-match] [-q | --quiet]
[--max-depth <depth>]
[--color | --no-color]
[-A <post-context>] [-B <pre-context>] [-C <context>]
@@ -158,6 +158,11 @@ OPTIONS
this flag is specified to limit the match to files that
have lines to match all of them.
-q::
--quiet::
Do not output matched lines; instead, exit with status 0 when
there is a match and with non-zero status when there isn't.
`<tree>...`::
Search blobs in the trees for specified patterns.

View File

@@ -14,7 +14,7 @@ DESCRIPTION
-----------
A simple CGI program to serve the contents of a Git repository to Git
clients accessing the repository over http:// and https:// protocols.
The program supports clients fetching using both the smart HTTP protcol
The program supports clients fetching using both the smart HTTP protocol
and the backwards-compatible dumb HTTP protocol, as well as clients
pushing using the smart HTTP protocol.

View File

@@ -25,7 +25,7 @@ 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. Each capability may be preceeded with '*'.
with a blank line. Each capability may be preceded with '*'.
This marks them mandatory for git version using the remote
helper to understand (unknown mandatory capability is fatal
error).

View File

@@ -33,7 +33,7 @@ OPTIONS
--stop-at-non-option::
Only meaningful in `--parseopt` mode. Lets the option parser stop at
the first non-option argument. This can be used to parse sub-commands
that take options themself.
that take options themselves.
--sq-quote::
Use 'git rev-parse' in shell quoting mode (see SQ-QUOTE

View File

@@ -218,7 +218,7 @@ OPTIONS
This option is only valid for the update command.
Rebase the current branch onto the commit recorded in the
superproject. If this option is given, the submodule's HEAD will not
be detached. If a a merge failure prevents this process, you will have
be detached. If a merge failure prevents this process, you will have
to resolve these failures with linkgit:git-rebase[1].
If the key `submodule.$name.update` is set to `rebase`, this option is
implicit.

View File

@@ -233,27 +233,27 @@ endif::git-rev-list[]
Pretend as if all the refs in `$GIT_DIR/refs/heads` are listed
on the command line as '<commit>'. If `pattern` is given, limit
branches to ones matching given shell glob. If pattern lacks '?',
'*', or '[', '/*' at the end is impiled.
'*', or '[', '/*' at the end is implied.
--tags[=pattern]::
Pretend as if all the refs in `$GIT_DIR/refs/tags` are listed
on the command line as '<commit>'. If `pattern` is given, limit
tags to ones matching given shell glob. If pattern lacks '?', '*',
or '[', '/*' at the end is impiled.
or '[', '/*' at the end is implied.
--remotes[=pattern]::
Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed
on the command line as '<commit>'. If `pattern`is given, limit
remote tracking branches to ones matching given shell glob.
If pattern lacks '?', '*', or '[', '/*' at the end is impiled.
If pattern lacks '?', '*', or '[', '/*' at the end is implied.
--glob=glob-pattern::
Pretend as if all the refs matching shell glob `glob-pattern`
are listed on the command line as '<commit>'. Leading 'refs/',
is automatically prepended if missing. If pattern lacks '?', '*',
or '[', '/*' at the end is impiled.
or '[', '/*' at the end is implied.
ifndef::git-rev-list[]

View File

@@ -51,7 +51,7 @@ The functions above do the following:
ENOENT; a diagnostic is printed only if .silent_exec_failure is 0.
. Otherwise, the program is run. If it terminates regularly, its exit
code is returned. No diagnistic is printed, even if the exit code is
code is returned. No diagnostic is printed, even if the exit code is
non-zero.
. If the program terminated due to a signal, then the return value is the

View File

@@ -149,7 +149,7 @@ advertisement list at all, but other refs may still appear.
The stream MUST include capability declarations behind a NUL on the
first ref. The peeled value of a ref (that is "ref^{}") MUST be
immediately after the ref itself, if presented. A conforming server
MUST peel the ref if its an annotated tag.
MUST peel the ref if it's an annotated tag.
----
advertised-refs = (no-refs / list-of-refs)
@@ -261,7 +261,7 @@ Without either multi_ack or multi_ack_detailed:
* upload-pack sends "NAK" on a flush-pkt if no common object
has been found yet. If one has been found, and thus an ACK
was already sent, its silent on the flush-pkt.
was already sent, it's silent on the flush-pkt.
After the client has gotten enough ACK responses that it can determine
that the server has enough information to send an efficient packfile
@@ -271,9 +271,9 @@ as common with the server, or the --date-order queue is empty), or the
client determines that it wants to give up (in the canonical implementation,
this is determined when the client sends 256 'have' lines without getting
any of them ACKed by the server - meaning there is nothing in common and
the server should just send all it's objects), then the client will send
the server should just send all of its objects), then the client will send
a 'done' command. The 'done' command signals to the server that the client
is ready to receive it's packfile data.
is ready to receive its packfile data.
However, the 256 limit *only* turns on in the canonical client
implementation if we have received at least one "ACK %s continue"
@@ -286,7 +286,7 @@ ACK after 'done' if there is at least one common base and multi_ack or
multi_ack_detailed is enabled. The server always sends NAK after 'done'
if there is no common base found.
Then the server will start sending it's packfile data.
Then the server will start sending its packfile data.
----
server-response = *ack_multi ack / nak

View File

@@ -60,7 +60,7 @@ doesn't, as in the following diagram:
If the client wants x,y and starts out by saying have F,S, the server
doesn't know what F,S is. Eventually the client says "have d" and
the server sends "ACK d continue" to let the client know to stop
walking down that line (so don't send c-b-a), but its not done yet,
walking down that line (so don't send c-b-a), but it's not done yet,
it needs a base for x. The client keeps going with S-R-Q, until a
gets reached, at which point the server has a clear base and it all
ends.
@@ -181,7 +181,7 @@ delete-refs
-----------
If the server sends back the 'delete-refs' capability, it means that
it is capable of accepting an zero-id value as the target
it is capable of accepting a zero-id value as the target
value of a reference update. It is not sent back by the client, it
simply informs the client that it can be sent zero-id values
to delete references.

View File

@@ -1196,7 +1196,7 @@ the time, you will want to commit your changes before you can merge,
and if you don't, then linkgit:git-stash[1] can take these changes
away while you're doing the merge, and reapply them afterwards.
If the changes are independant enough, Git will automatically complete
If the changes are independent enough, Git will automatically complete
the merge and commit the result (or reuse an existing commit in case
of <<fast-forwards,fast-forward>>, see below). On the other hand,
if there are conflicts--for example, if the same file is

View File

@@ -180,9 +180,6 @@ all::
# If not set it defaults to the bare 'wish'. If it is set to the empty
# string then NO_TCLTK will be forced (this is used by configure script).
#
# Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit
# parallel delta searching when packing objects.
#
# Define INTERNAL_QSORT to use Git's implementation of qsort(), which
# is a simplified version of the merge sort used in glibc. This is
# recommended if Git triggers O(n^2) behavior in your platform's qsort().
@@ -722,12 +719,10 @@ EXTLIBS =
ifeq ($(uname_S),Linux)
NO_STRLCPY = YesPlease
NO_MKSTEMPS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
NO_STRLCPY = YesPlease
NO_MKSTEMPS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),UnixWare)
CC = cc
@@ -781,7 +776,6 @@ ifeq ($(uname_S),Darwin)
NO_STRLCPY = YesPlease
endif
NO_MEMMEM = YesPlease
THREADED_DELTA_SEARCH = YesPlease
USE_ST_TIMESPEC = YesPlease
endif
ifeq ($(uname_S),SunOS)
@@ -794,7 +788,6 @@ ifeq ($(uname_S),SunOS)
NO_MKDTEMP = YesPlease
NO_MKSTEMPS = YesPlease
NO_REGEX = YesPlease
THREADED_DELTA_SEARCH = YesPlease
ifeq ($(uname_R),5.7)
NEEDS_RESOLV = YesPlease
NO_IPV6 = YesPlease
@@ -850,7 +843,6 @@ ifeq ($(uname_S),FreeBSD)
BASIC_LDFLAGS += -L/usr/local/lib
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
USE_ST_TIMESPEC = YesPlease
THREADED_DELTA_SEARCH = YesPlease
ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
PTHREAD_LIBS = -pthread
NO_UINTMAX_T = YesPlease
@@ -864,7 +856,6 @@ ifeq ($(uname_S),OpenBSD)
NEEDS_LIBICONV = YesPlease
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),NetBSD)
ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
@@ -872,7 +863,6 @@ ifeq ($(uname_S),NetBSD)
endif
BASIC_CFLAGS += -I/usr/pkg/include
BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
THREADED_DELTA_SEARCH = YesPlease
USE_ST_TIMESPEC = YesPlease
NO_MKSTEMPS = YesPlease
endif
@@ -887,9 +877,7 @@ ifeq ($(uname_S),AIX)
INTERNAL_QSORT = UnfortunatelyYes
NEEDS_LIBICONV=YesPlease
BASIC_CFLAGS += -D_LARGE_FILES
ifneq ($(shell expr "$(uname_V)" : '[1234]'),1)
THREADED_DELTA_SEARCH = YesPlease
else
ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
NO_PTHREADS = YesPlease
endif
endif
@@ -915,7 +903,6 @@ ifeq ($(uname_S),IRIX)
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH = /usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),IRIX64)
NO_SETENV=YesPlease
@@ -934,7 +921,6 @@ ifeq ($(uname_S),IRIX64)
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH=/usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),HP-UX)
NO_IPV6=YesPlease
@@ -984,7 +970,6 @@ ifeq ($(uname_S),Windows)
NO_CURL = YesPlease
NO_PYTHON = YesPlease
BLK_SHA1 = YesPlease
THREADED_DELTA_SEARCH = YesPlease
CC = compat/vcbuild/scripts/clink.pl
AR = compat/vcbuild/scripts/lib.pl
@@ -1036,7 +1021,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_REGEX = YesPlease
NO_PYTHON = YesPlease
BLK_SHA1 = YesPlease
THREADED_DELTA_SEARCH = YesPlease
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
@@ -1334,16 +1318,12 @@ ifdef RUNTIME_PREFIX
endif
ifdef NO_PTHREADS
THREADED_DELTA_SEARCH =
BASIC_CFLAGS += -DNO_PTHREADS
else
EXTLIBS += $(PTHREAD_LIBS)
endif
ifdef THREADED_DELTA_SEARCH
BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
LIB_OBJS += thread-utils.o
endif
ifdef DIR_HAS_BSD_GROUP_SEMANTICS
COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
endif

View File

@@ -9,8 +9,6 @@
#include "builtin.h"
#include "utf8.h"
#define BLOCKING (1ul << 14)
/*
* FIXME! Share the code with "write-tree.c"
*/

View File

@@ -358,7 +358,7 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
if (!is_absolute_path(given_config_file) && prefix)
config_exclusive_filename = prefix_filename(prefix,
strlen(prefix),
argv[2]);
given_config_file);
else
config_exclusive_filename = given_config_file;
}

View File

@@ -16,11 +16,276 @@
#include "quote.h"
#include "dir.h"
#ifndef NO_PTHREADS
#include "thread-utils.h"
#include <pthread.h>
#endif
static char const * const grep_usage[] = {
"git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
NULL
};
static int use_threads = 1;
#ifndef NO_PTHREADS
#define THREADS 8
static pthread_t threads[THREADS];
static void *load_sha1(const unsigned char *sha1, unsigned long *size,
const char *name);
static void *load_file(const char *filename, size_t *sz);
enum work_type {WORK_SHA1, WORK_FILE};
/* We use one producer thread and THREADS consumer
* threads. The producer adds struct work_items to 'todo' and the
* consumers pick work items from the same array.
*/
struct work_item
{
enum work_type type;
char *name;
/* if type == WORK_SHA1, then 'identifier' is a SHA1,
* otherwise type == WORK_FILE, and 'identifier' is a NUL
* terminated filename.
*/
void *identifier;
char done;
struct strbuf out;
};
/* In the range [todo_done, todo_start) in 'todo' we have work_items
* that have been or are processed by a consumer thread. We haven't
* written the result for these to stdout yet.
*
* The work_items in [todo_start, todo_end) are waiting to be picked
* up by a consumer thread.
*
* The ranges are modulo TODO_SIZE.
*/
#define TODO_SIZE 128
static struct work_item todo[TODO_SIZE];
static int todo_start;
static int todo_end;
static int todo_done;
/* Has all work items been added? */
static int all_work_added;
/* This lock protects all the variables above. */
static pthread_mutex_t grep_mutex;
/* Used to serialize calls to read_sha1_file. */
static pthread_mutex_t read_sha1_mutex;
#define grep_lock() pthread_mutex_lock(&grep_mutex)
#define grep_unlock() pthread_mutex_unlock(&grep_mutex)
#define read_sha1_lock() pthread_mutex_lock(&read_sha1_mutex)
#define read_sha1_unlock() pthread_mutex_unlock(&read_sha1_mutex)
/* Signalled when a new work_item is added to todo. */
static pthread_cond_t cond_add;
/* Signalled when the result from one work_item is written to
* stdout.
*/
static pthread_cond_t cond_write;
/* Signalled when we are finished with everything. */
static pthread_cond_t cond_result;
static void add_work(enum work_type type, char *name, void *id)
{
grep_lock();
while ((todo_end+1) % ARRAY_SIZE(todo) == todo_done) {
pthread_cond_wait(&cond_write, &grep_mutex);
}
todo[todo_end].type = type;
todo[todo_end].name = name;
todo[todo_end].identifier = id;
todo[todo_end].done = 0;
strbuf_reset(&todo[todo_end].out);
todo_end = (todo_end + 1) % ARRAY_SIZE(todo);
pthread_cond_signal(&cond_add);
grep_unlock();
}
static struct work_item *get_work(void)
{
struct work_item *ret;
grep_lock();
while (todo_start == todo_end && !all_work_added) {
pthread_cond_wait(&cond_add, &grep_mutex);
}
if (todo_start == todo_end && all_work_added) {
ret = NULL;
} else {
ret = &todo[todo_start];
todo_start = (todo_start + 1) % ARRAY_SIZE(todo);
}
grep_unlock();
return ret;
}
static void grep_sha1_async(struct grep_opt *opt, char *name,
const unsigned char *sha1)
{
unsigned char *s;
s = xmalloc(20);
memcpy(s, sha1, 20);
add_work(WORK_SHA1, name, s);
}
static void grep_file_async(struct grep_opt *opt, char *name,
const char *filename)
{
add_work(WORK_FILE, name, xstrdup(filename));
}
static void work_done(struct work_item *w)
{
int old_done;
grep_lock();
w->done = 1;
old_done = todo_done;
for(; todo[todo_done].done && todo_done != todo_start;
todo_done = (todo_done+1) % ARRAY_SIZE(todo)) {
w = &todo[todo_done];
write_or_die(1, w->out.buf, w->out.len);
free(w->name);
free(w->identifier);
}
if (old_done != todo_done)
pthread_cond_signal(&cond_write);
if (all_work_added && todo_done == todo_end)
pthread_cond_signal(&cond_result);
grep_unlock();
}
static void *run(void *arg)
{
int hit = 0;
struct grep_opt *opt = arg;
while (1) {
struct work_item *w = get_work();
if (!w)
break;
opt->output_priv = w;
if (w->type == WORK_SHA1) {
unsigned long sz;
void* data = load_sha1(w->identifier, &sz, w->name);
if (data) {
hit |= grep_buffer(opt, w->name, data, sz);
free(data);
}
} else if (w->type == WORK_FILE) {
size_t sz;
void* data = load_file(w->identifier, &sz);
if (data) {
hit |= grep_buffer(opt, w->name, data, sz);
free(data);
}
} else {
assert(0);
}
work_done(w);
}
free_grep_patterns(arg);
free(arg);
return (void*) (intptr_t) hit;
}
static void strbuf_out(struct grep_opt *opt, const void *buf, size_t size)
{
struct work_item *w = opt->output_priv;
strbuf_add(&w->out, buf, size);
}
static void start_threads(struct grep_opt *opt)
{
int i;
pthread_mutex_init(&grep_mutex, NULL);
pthread_mutex_init(&read_sha1_mutex, NULL);
pthread_cond_init(&cond_add, NULL);
pthread_cond_init(&cond_write, NULL);
pthread_cond_init(&cond_result, NULL);
for (i = 0; i < ARRAY_SIZE(todo); i++) {
strbuf_init(&todo[i].out, 0);
}
for (i = 0; i < ARRAY_SIZE(threads); i++) {
int err;
struct grep_opt *o = grep_opt_dup(opt);
o->output = strbuf_out;
compile_grep_patterns(o);
err = pthread_create(&threads[i], NULL, run, o);
if (err)
die("grep: failed to create thread: %s",
strerror(err));
}
}
static int wait_all(void)
{
int hit = 0;
int i;
grep_lock();
all_work_added = 1;
/* Wait until all work is done. */
while (todo_done != todo_end)
pthread_cond_wait(&cond_result, &grep_mutex);
/* Wake up all the consumer threads so they can see that there
* is no more work to do.
*/
pthread_cond_broadcast(&cond_add);
grep_unlock();
for (i = 0; i < ARRAY_SIZE(threads); i++) {
void *h;
pthread_join(threads[i], &h);
hit |= (int) (intptr_t) h;
}
pthread_mutex_destroy(&grep_mutex);
pthread_mutex_destroy(&read_sha1_mutex);
pthread_cond_destroy(&cond_add);
pthread_cond_destroy(&cond_write);
pthread_cond_destroy(&cond_result);
return hit;
}
#else /* !NO_PTHREADS */
#define read_sha1_lock()
#define read_sha1_unlock()
static int wait_all(void)
{
return 0;
}
#endif
static int grep_config(const char *var, const char *value, void *cb)
{
struct grep_opt *opt = cb;
@@ -144,37 +409,64 @@ static int pathspec_matches(const char **paths, const char *name, int max_depth)
return 0;
}
static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char *name, int tree_name_len)
static void *load_sha1(const unsigned char *sha1, unsigned long *size,
const char *name)
{
unsigned long size;
char *data;
enum object_type type;
int hit;
struct strbuf pathbuf = STRBUF_INIT;
char *data;
data = read_sha1_file(sha1, &type, &size);
if (!data) {
read_sha1_lock();
data = read_sha1_file(sha1, &type, size);
read_sha1_unlock();
if (!data)
error("'%s': unable to read %s", name, sha1_to_hex(sha1));
return 0;
}
if (opt->relative && opt->prefix_length) {
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);
return hit;
return data;
}
static int grep_file(struct grep_opt *opt, const char *filename)
static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
const char *filename, int tree_name_len)
{
struct strbuf pathbuf = STRBUF_INIT;
char *name;
if (opt->relative && opt->prefix_length) {
quote_path_relative(filename + tree_name_len, -1, &pathbuf,
opt->prefix);
strbuf_insert(&pathbuf, 0, filename, tree_name_len);
} else {
strbuf_addstr(&pathbuf, filename);
}
name = strbuf_detach(&pathbuf, NULL);
#ifndef NO_PTHREADS
if (use_threads) {
grep_sha1_async(opt, name, sha1);
return 0;
} else
#endif
{
int hit;
unsigned long sz;
void *data = load_sha1(sha1, &sz, name);
if (!data)
hit = 0;
else
hit = grep_buffer(opt, name, data, sz);
free(data);
free(name);
return hit;
}
}
static void *load_file(const char *filename, size_t *sz)
{
struct stat st;
int i;
char *data;
size_t sz;
struct strbuf buf = STRBUF_INIT;
int i;
if (lstat(filename, &st) < 0) {
err_ret:
@@ -184,25 +476,52 @@ static int grep_file(struct grep_opt *opt, const char *filename)
}
if (!S_ISREG(st.st_mode))
return 0;
sz = xsize_t(st.st_size);
*sz = xsize_t(st.st_size);
i = open(filename, O_RDONLY);
if (i < 0)
goto err_ret;
data = xmalloc(sz + 1);
if (st.st_size != read_in_full(i, data, sz)) {
data = xmalloc(*sz + 1);
if (st.st_size != read_in_full(i, data, *sz)) {
error("'%s': short read %s", filename, strerror(errno));
close(i);
free(data);
return 0;
}
close(i);
data[sz] = 0;
data[*sz] = 0;
return data;
}
static int grep_file(struct grep_opt *opt, const char *filename)
{
struct strbuf buf = STRBUF_INIT;
char *name;
if (opt->relative && 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;
quote_path_relative(filename, -1, &buf, opt->prefix);
else
strbuf_addstr(&buf, filename);
name = strbuf_detach(&buf, NULL);
#ifndef NO_PTHREADS
if (use_threads) {
grep_file_async(opt, name, filename);
return 0;
} else
#endif
{
int hit;
size_t sz;
void *data = load_file(filename, &sz);
if (!data)
hit = 0;
else
hit = grep_buffer(opt, name, data, sz);
free(data);
free(name);
return hit;
}
}
static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
@@ -236,6 +555,8 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
!strcmp(ce->name, active_cache[nr]->name));
nr--; /* compensate for loop control */
}
if (hit && opt->status_only)
break;
}
free_grep_patterns(opt);
return hit;
@@ -285,7 +606,10 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
void *data;
unsigned long size;
read_sha1_lock();
data = read_sha1_file(entry.sha1, &type, &size);
read_sha1_unlock();
if (!data)
die("unable to read tree (%s)",
sha1_to_hex(entry.sha1));
@@ -293,6 +617,8 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
hit |= grep_tree(opt, paths, &sub, tree_name, down);
free(data);
}
if (hit && opt->status_only)
break;
}
strbuf_release(&pathbuf);
return hit;
@@ -329,8 +655,11 @@ static int grep_directory(struct grep_opt *opt, const char **paths)
setup_standard_excludes(&dir);
fill_directory(&dir, paths);
for (i = 0; i < dir.nr; i++)
for (i = 0; i < dir.nr; i++) {
hit |= grep_file(opt, dir.entries[i]->name);
if (hit && opt->status_only)
break;
}
free_grep_patterns(opt);
return hit;
}
@@ -505,6 +834,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
{ OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
close_callback },
OPT_BOOLEAN('q', "quiet", &opt.status_only,
"indicate hit with exit status without output"),
OPT_BOOLEAN(0, "all-match", &opt.all_match,
"show only matches from files that match all patterns"),
OPT_GROUP(""),
@@ -572,6 +903,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.regflags |= REG_ICASE;
if ((opt.regflags != REG_NEWLINE) && opt.fixed)
die("cannot mix --fixed-strings and regexp");
#ifndef NO_PTHREADS
if (online_cpus() == 1 || !grep_threads_ok(&opt))
use_threads = 0;
if (use_threads)
start_threads(&opt);
#else
use_threads = 0;
#endif
compile_grep_patterns(&opt);
/* Check revs and then paths */
@@ -609,17 +951,26 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
if (!use_index) {
int hit;
if (cached)
die("--cached cannot be used with --no-index.");
if (list.nr)
die("--no-index cannot be used with revs.");
return !grep_directory(&opt, paths);
hit = grep_directory(&opt, paths);
if (use_threads)
hit |= wait_all();
return !hit;
}
if (!list.nr) {
int hit;
if (!cached)
setup_work_tree();
return !grep_cache(&opt, paths, cached);
hit = grep_cache(&opt, paths, cached);
if (use_threads)
hit |= wait_all();
return !hit;
}
if (cached)
@@ -628,9 +979,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
for (i = 0; i < list.nr; i++) {
struct object *real_obj;
real_obj = deref_tag(list.objects[i].item, NULL, 0);
if (grep_object(&opt, paths, real_obj, list.objects[i].name))
if (grep_object(&opt, paths, real_obj, list.objects[i].name)) {
hit = 1;
if (opt.status_only)
break;
}
}
if (use_threads)
hit |= wait_all();
free_grep_patterns(&opt);
return !hit;
}

View File

@@ -17,7 +17,7 @@
#include "progress.h"
#include "refs.h"
#ifdef THREADED_DELTA_SEARCH
#ifndef NO_PTHREADS
#include "thread-utils.h"
#include <pthread.h>
#endif
@@ -1255,7 +1255,7 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
return 0;
}
#ifdef THREADED_DELTA_SEARCH
#ifndef NO_PTHREADS
static pthread_mutex_t read_mutex;
#define read_lock() pthread_mutex_lock(&read_mutex)
@@ -1380,7 +1380,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
/*
* Handle memory allocation outside of the cache
* accounting lock. Compiler will optimize the strangeness
* away when THREADED_DELTA_SEARCH is not defined.
* away when NO_PTHREADS is defined.
*/
free(trg_entry->delta_data);
cache_lock();
@@ -1567,7 +1567,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
free(array);
}
#ifdef THREADED_DELTA_SEARCH
#ifndef NO_PTHREADS
/*
* The main thread waits on the condition that (at least) one of the workers
@@ -1899,7 +1899,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
if (delta_search_threads < 0)
die("invalid number of threads specified (%d)",
delta_search_threads);
#ifndef THREADED_DELTA_SEARCH
#ifdef NO_PTHREADS
if (delta_search_threads != 1)
warning("no threads support, ignoring %s", k);
#endif
@@ -2227,7 +2227,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
delta_search_threads = strtoul(arg+10, &end, 0);
if (!arg[10] || *end || delta_search_threads < 0)
usage(pack_usage);
#ifndef THREADED_DELTA_SEARCH
#ifdef NO_PTHREADS
if (delta_search_threads != 1)
warning("no threads support, "
"ignoring %s", arg);

View File

@@ -52,7 +52,7 @@ static void set_refspecs(const char **refs, int nr)
} else if (deleterefs && !strchr(ref, ':')) {
char *delref;
int len = strlen(ref)+1;
delref = xmalloc(len);
delref = xmalloc(len+1);
strcpy(delref, ":");
strcat(delref, ref);
ref = delref;

View File

@@ -762,7 +762,8 @@ const char *show_date_relative(unsigned long time, int tz,
size_t timebuf_size);
int parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
unsigned long approxidate(const char *);
#define approxidate(s) approxidate_careful((s), NULL)
unsigned long approxidate_careful(const char *, int *);
unsigned long approxidate_relative(const char *date, const struct timeval *now);
enum date_mode parse_date_format(const char *format);

View File

@@ -224,7 +224,7 @@ int unregister_shallow(const unsigned char *sha1)
if (pos < 0)
return -1;
if (pos + 1 < commit_graft_nr)
memcpy(commit_graft + pos, commit_graft + pos + 1,
memmove(commit_graft + pos, commit_graft + pos + 1,
sizeof(struct commit_graft *)
* (commit_graft_nr - pos - 1));
commit_graft_nr--;

View File

@@ -52,24 +52,38 @@ int win32_pthread_join(pthread_t *thread, void **value_ptr)
int pthread_cond_init(pthread_cond_t *cond, const void *unused)
{
cond->waiters = 0;
cond->was_broadcast = 0;
InitializeCriticalSection(&cond->waiters_lock);
cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
if (!cond->sema)
die("CreateSemaphore() failed");
cond->continue_broadcast = CreateEvent(NULL, /* security */
FALSE, /* auto-reset */
FALSE, /* not signaled */
NULL); /* name */
if (!cond->continue_broadcast)
die("CreateEvent() failed");
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond)
{
CloseHandle(cond->sema);
cond->sema = NULL;
CloseHandle(cond->continue_broadcast);
DeleteCriticalSection(&cond->waiters_lock);
return 0;
}
int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
{
InterlockedIncrement(&cond->waiters);
int last_waiter;
EnterCriticalSection(&cond->waiters_lock);
cond->waiters++;
LeaveCriticalSection(&cond->waiters_lock);
/*
* Unlock external mutex and wait for signal.
@@ -82,22 +96,52 @@ int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
/* let's wait - ignore return value */
WaitForSingleObject(cond->sema, INFINITE);
/* we're done waiting, so make sure we decrease waiters count */
InterlockedDecrement(&cond->waiters);
/*
* Decrease waiters count. If we are the last waiter, then we must
* notify the broadcasting thread that it can continue.
* But if we continued due to cond_signal, we do not have to do that
* because the signaling thread knows that only one waiter continued.
*/
EnterCriticalSection(&cond->waiters_lock);
cond->waiters--;
last_waiter = cond->was_broadcast && cond->waiters == 0;
LeaveCriticalSection(&cond->waiters_lock);
if (last_waiter) {
/*
* cond_broadcast was issued while mutex was held. This means
* that all other waiters have continued, but are contending
* for the mutex at the end of this function because the
* broadcasting thread did not leave cond_broadcast, yet.
* (This is so that it can be sure that each waiter has
* consumed exactly one slice of the semaphor.)
* The last waiter must tell the broadcasting thread that it
* can go on.
*/
SetEvent(cond->continue_broadcast);
/*
* Now we go on to contend with all other waiters for
* the mutex. Auf in den Kampf!
*/
}
/* lock external mutex again */
EnterCriticalSection(mutex);
return 0;
}
/*
* IMPORTANT: This implementation requires that pthread_cond_signal
* is called while the mutex is held that is used in the corresponding
* pthread_cond_wait calls!
*/
int pthread_cond_signal(pthread_cond_t *cond)
{
/*
* Access to waiters count is atomic; see "Interlocked Variable Access"
* http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx
*/
int have_waiters = cond->waiters > 0;
int have_waiters;
EnterCriticalSection(&cond->waiters_lock);
have_waiters = cond->waiters > 0;
LeaveCriticalSection(&cond->waiters_lock);
/*
* Signal only when there are waiters
@@ -108,3 +152,37 @@ int pthread_cond_signal(pthread_cond_t *cond)
else
return 0;
}
/*
* DOUBLY IMPORTANT: This implementation requires that pthread_cond_broadcast
* is called while the mutex is held that is used in the corresponding
* pthread_cond_wait calls!
*/
int pthread_cond_broadcast(pthread_cond_t *cond)
{
EnterCriticalSection(&cond->waiters_lock);
if ((cond->was_broadcast = cond->waiters > 0)) {
/* wake up all waiters */
ReleaseSemaphore(cond->sema, cond->waiters, NULL);
LeaveCriticalSection(&cond->waiters_lock);
/*
* At this point all waiters continue. Each one takes its
* slice of the semaphor. Now it's our turn to wait: Since
* the external mutex is held, no thread can leave cond_wait,
* yet. For this reason, we can be sure that no thread gets
* a chance to eat *more* than one slice. OTOH, it means
* that the last waiter must send us a wake-up.
*/
WaitForSingleObject(cond->continue_broadcast, INFINITE);
/*
* Since the external mutex is held, no thread can enter
* cond_wait, and, hence, it is safe to reset this flag
* without cond->waiters_lock held.
*/
cond->was_broadcast = 0;
} else {
LeaveCriticalSection(&cond->waiters_lock);
}
return 0;
}

View File

@@ -32,17 +32,18 @@
* See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/
typedef struct {
volatile LONG waiters;
LONG waiters;
int was_broadcast;
CRITICAL_SECTION waiters_lock;
HANDLE sema;
HANDLE continue_broadcast;
} pthread_cond_t;
extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
extern int pthread_cond_destroy(pthread_cond_t *cond);
extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
extern int pthread_cond_signal(pthread_cond_t *cond);
extern int pthread_cond_broadcast(pthread_cond_t *cond);
/*
* Simple thread creation implementation using pthread API

View File

@@ -56,5 +56,4 @@ NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
FREAD_READS_DIRECTORIES=@FREAD_READS_DIRECTORIES@
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
NO_PTHREADS=@NO_PTHREADS@
THREADED_DELTA_SEARCH=@THREADED_DELTA_SEARCH@
PTHREAD_LIBS=@PTHREAD_LIBS@

View File

@@ -762,10 +762,9 @@ AC_SUBST(NO_MKSTEMPS)
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
# Enable it on Windows. By default, symrefs are still used.
#
# Define NO_PTHREADS if we do not have pthreads
# Define NO_PTHREADS if we do not have pthreads.
#
# Define PTHREAD_LIBS to the linker flag used for Pthread support and define
# THREADED_DELTA_SEARCH if Pthreads are available.
# Define PTHREAD_LIBS to the linker flag used for Pthread support.
AC_DEFUN([PTHREADTEST_SRC], [
#include <pthread.h>
@@ -782,7 +781,6 @@ dnl [[pthread_mutex_t test_mutex;]]
dnl )])
NO_PTHREADS=UnfortunatelyYes
THREADED_DELTA_SEARCH=
PTHREAD_LIBS=
if test -n "$USER_NOPTHREAD"; then
@@ -798,7 +796,6 @@ elif test -z "$PTHREAD_CFLAGS"; then
[AC_MSG_RESULT([yes])
NO_PTHREADS=
PTHREAD_LIBS="$opt"
THREADED_DELTA_SEARCH=YesPlease
break
],
[AC_MSG_RESULT([no])])
@@ -812,7 +809,6 @@ else
[AC_MSG_RESULT([yes])
NO_PTHREADS=
PTHREAD_LIBS="$PTHREAD_CFLAGS"
THREADED_DELTA_SEARCH=YesPlease
],
[AC_MSG_RESULT([no])])
@@ -823,7 +819,6 @@ CFLAGS="$old_CFLAGS"
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(NO_PTHREADS)
AC_SUBST(THREADED_DELTA_SEARCH)
## Output files
AC_CONFIG_FILES(["${config_file}":"${config_in}":"${config_append}"])

View File

@@ -502,12 +502,18 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
c = ':';
}
/*
* Don't do destructive transforms with git:// as that
* protocol code does '[]' dewrapping of its own.
*/
if (host[0] == '[') {
end = strchr(host + 1, ']');
if (end) {
*end = 0;
if (protocol != PROTO_GIT) {
*end = 0;
host++;
}
end++;
host++;
} else
end = host;
} else
@@ -613,8 +619,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
NULL
};
conn->env = env;
*arg++ = "sh";
*arg++ = "-c";
conn->use_shell = 1;
}
*arg++ = cmd.buf;
*arg = NULL;

View File

@@ -568,6 +568,7 @@ __git_list_porcelain_commands ()
read-tree) : plumbing;;
receive-pack) : plumbing;;
reflog) : plumbing;;
remote-*) : transport;;
repo-config) : deprecated;;
rerere) : plumbing;;
rev-list) : plumbing;;
@@ -1306,6 +1307,24 @@ _git_name_rev ()
__gitcomp "--tags --all --stdin"
}
_git_notes ()
{
local subcommands="edit show"
if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
__gitcomp "$subcommands"
return
fi
case "${COMP_WORDS[COMP_CWORD-1]}" in
-m|-F)
COMPREPLY=()
;;
*)
__gitcomp "$(__git_refs)"
;;
esac
}
_git_pull ()
{
__git_complete_strategy && return
@@ -2218,6 +2237,7 @@ _git ()
merge-base) _git_merge_base ;;
mv) _git_mv ;;
name-rev) _git_name_rev ;;
notes) _git_notes ;;
pull) _git_pull ;;
push) _git_push ;;
rebase) _git_rebase ;;

View File

@@ -399,6 +399,33 @@ static char *xstrdup_tolower(const char *str)
return dup;
}
static void parse_host_and_port(char *hostport, char **host,
char **port)
{
if (*hostport == '[') {
char *end;
end = strchr(hostport, ']');
if (!end)
die("Invalid reqeuest ('[' without ']')");
*end = '\0';
*host = hostport + 1;
if (!end[1])
*port = NULL;
else if (end[1] == ':')
*port = end + 2;
else
die("Garbage after end of host part");
} else {
*host = hostport;
*port = strrchr(hostport, ':');
if (*port) {
*port = '\0';
++*port;
}
}
}
/*
* Read the host as supplied by the client connection.
*/
@@ -415,11 +442,10 @@ static void parse_host_arg(char *extra_args, int buflen)
vallen = strlen(val) + 1;
if (*val) {
/* Split <host>:<port> at colon. */
char *host = val;
char *port = strrchr(host, ':');
char *host;
char *port;
parse_host_and_port(val, &host, &port);
if (port) {
*port = 0;
port++;
free(tcp_port);
tcp_port = xstrdup(port);
}

43
date.c
View File

@@ -696,6 +696,11 @@ static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
return n;
}
static void date_now(struct tm *tm, struct tm *now, int *num)
{
update_tm(tm, now, 0);
}
static void date_yesterday(struct tm *tm, struct tm *now, int *num)
{
update_tm(tm, now, 24*60*60);
@@ -770,6 +775,7 @@ static const struct special {
{ "PM", date_pm },
{ "AM", date_am },
{ "never", date_never },
{ "now", date_now },
{ NULL }
};
@@ -790,7 +796,7 @@ static const struct typelen {
{ NULL }
};
static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num)
static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num, int *touched)
{
const struct typelen *tl;
const struct special *s;
@@ -804,6 +810,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
int match = match_string(date, month_names[i]);
if (match >= 3) {
tm->tm_mon = i;
*touched = 1;
return end;
}
}
@@ -812,6 +819,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
int len = strlen(s->name);
if (match_string(date, s->name) == len) {
s->fn(tm, now, num);
*touched = 1;
return end;
}
}
@@ -821,11 +829,14 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
int len = strlen(number_name[i]);
if (match_string(date, number_name[i]) == len) {
*num = i;
*touched = 1;
return end;
}
}
if (match_string(date, "last") == 4)
if (match_string(date, "last") == 4) {
*num = 1;
*touched = 1;
}
return end;
}
@@ -835,6 +846,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
if (match_string(date, tl->type) >= len-1) {
update_tm(tm, now, tl->length * *num);
*num = 0;
*touched = 1;
return end;
}
tl++;
@@ -852,6 +864,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
diff += 7*n;
update_tm(tm, now, diff * 24 * 60 * 60);
*touched = 1;
return end;
}
}
@@ -866,6 +879,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
tm->tm_year--;
}
tm->tm_mon = n;
*touched = 1;
return end;
}
@@ -873,6 +887,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
update_tm(tm, now, 0); /* fill in date fields if needed */
tm->tm_year -= *num;
*num = 0;
*touched = 1;
return end;
}
@@ -929,9 +944,12 @@ static void pending_number(struct tm *tm, int *num)
}
}
static unsigned long approxidate_str(const char *date, const struct timeval *tv)
static unsigned long approxidate_str(const char *date,
const struct timeval *tv,
int *error_ret)
{
int number = 0;
int touched = 0;
struct tm tm, now;
time_t time_sec;
@@ -951,33 +969,42 @@ static unsigned long approxidate_str(const char *date, const struct timeval *tv)
if (isdigit(c)) {
pending_number(&tm, &number);
date = approxidate_digit(date-1, &tm, &number);
touched = 1;
continue;
}
if (isalpha(c))
date = approxidate_alpha(date-1, &tm, &now, &number);
date = approxidate_alpha(date-1, &tm, &now, &number, &touched);
}
pending_number(&tm, &number);
if (!touched)
*error_ret = 1;
return update_tm(&tm, &now, 0);
}
unsigned long approxidate_relative(const char *date, const struct timeval *tv)
{
char buffer[50];
int errors = 0;
if (parse_date(date, buffer, sizeof(buffer)) > 0)
return strtoul(buffer, NULL, 0);
return approxidate_str(date, tv);
return approxidate_str(date, tv, &errors);
}
unsigned long approxidate(const char *date)
unsigned long approxidate_careful(const char *date, int *error_ret)
{
struct timeval tv;
char buffer[50];
int dummy = 0;
if (!error_ret)
error_ret = &dummy;
if (parse_date(date, buffer, sizeof(buffer)) > 0)
if (parse_date(date, buffer, sizeof(buffer)) > 0) {
*error_ret = 0;
return strtoul(buffer, NULL, 0);
}
gettimeofday(&tv, NULL);
return approxidate_str(date, &tv);
return approxidate_str(date, &tv, error_ret);
}

View File

@@ -161,7 +161,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
continue;
}
if ((ce_uptodate(ce) && !S_ISGITLINK(ce->ce_mode)) || ce_skip_worktree(ce))
if (ce_uptodate(ce) || ce_skip_worktree(ce))
continue;
/* If CE_VALID is set, don't look at workdir for file removal */
@@ -179,6 +179,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
}
changed = ce_match_stat(ce, &st, ce_option);
if (S_ISGITLINK(ce->ce_mode)
&& !DIFF_OPT_TST(&revs->diffopt, IGNORE_SUBMODULES)
&& (!changed || (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
&& is_submodule_modified(ce->name)) {
changed = 1;
@@ -220,7 +221,7 @@ static int get_stat_data(struct cache_entry *ce,
const unsigned char **sha1p,
unsigned int *modep,
int cached, int match_missing,
unsigned *dirty_submodule, int output_format)
unsigned *dirty_submodule, struct diff_options *diffopt)
{
const unsigned char *sha1 = ce->sha1;
unsigned int mode = ce->ce_mode;
@@ -241,7 +242,8 @@ static int get_stat_data(struct cache_entry *ce,
}
changed = ce_match_stat(ce, &st, 0);
if (S_ISGITLINK(ce->ce_mode)
&& (!changed || (output_format & DIFF_FORMAT_PATCH))
&& !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)
&& (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH))
&& is_submodule_modified(ce->name)) {
changed = 1;
*dirty_submodule = 1;
@@ -270,7 +272,7 @@ static void show_new_file(struct rev_info *revs,
* the working copy.
*/
if (get_stat_data(new, &sha1, &mode, cached, match_missing,
&dirty_submodule, revs->diffopt.output_format) < 0)
&dirty_submodule, &revs->diffopt) < 0)
return;
diff_index_show_file(revs, "+", new, sha1, mode, dirty_submodule);
@@ -287,7 +289,7 @@ static int show_modified(struct rev_info *revs,
unsigned dirty_submodule = 0;
if (get_stat_data(new, &sha1, &mode, cached, match_missing,
&dirty_submodule, revs->diffopt.output_format) < 0) {
&dirty_submodule, &revs->diffopt) < 0) {
if (report_missing)
diff_index_show_file(revs, "-", old,
old->sha1, old->ce_mode, 0);

2
diff.c
View File

@@ -1615,7 +1615,7 @@ static void builtin_diff(const char *name_a,
const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
show_submodule_summary(o->file, one ? one->path : two->path,
one->sha1, two->sha1,
one->sha1, two->sha1, two->dirty_submodule,
del, add, reset);
return;
}

View File

@@ -205,7 +205,8 @@ check_patch_format () {
# discarding the indented remainder of folded lines,
# and see if it looks like that they all begin with the
# header field names...
sed -n -e '/^$/q' -e '/^[ ]/d' -e p "$1" |
tr -d '\015' <"$1" |
sed -n -e '/^$/q' -e '/^[ ]/d' -e p |
sane_egrep -v '^[!-9;-~]+:' >/dev/null ||
patch_format=mbox
fi

View File

@@ -348,6 +348,7 @@ extern void release_pack_memory(size_t, int);
extern char *xstrdup(const char *str);
extern void *xmalloc(size_t size);
extern void *xmallocz(size_t size);
extern void *xmemdupz(const void *data, size_t len);
extern char *xstrndup(const char *str, size_t len);
extern void *xrealloc(void *ptr, size_t size);

View File

@@ -408,7 +408,7 @@ sub req_Directory
$state->{localdir} = $data;
$state->{repository} = $repository;
$state->{path} = $repository;
$state->{path} =~ s/^$state->{CVSROOT}\///;
$state->{path} =~ s/^\Q$state->{CVSROOT}\E\///;
$state->{module} = $1 if ($state->{path} =~ s/^(.*?)(\/|$)//);
$state->{path} .= "/" if ( $state->{path} =~ /\S/ );

View File

@@ -462,11 +462,11 @@ if [ "$filter_tag_name" ]; then
"$new_sha1" "$new_ref"
git cat-file tag "$ref" |
sed -n \
-e "1,/^$/{
-e '1,/^$/{
/^object /d
/^type /d
/^tag /d
}" \
}' \
-e '/^-----BEGIN PGP SIGNATURE-----/q' \
-e 'p' ) |
git mktag) ||

View File

@@ -320,7 +320,7 @@ EOF
else
# plain-old CGI
resolve_full_httpd
list_mods=$(echo "$full_httpd" | sed "s/-f$/-l/")
list_mods=$(echo "$full_httpd" | sed 's/-f$/-l/')
$list_mods | sane_grep 'mod_cgi\.c' >/dev/null 2>&1 || \
if test -f "$module_path/mod_cgi.so"
then

View File

@@ -1,3 +1,4 @@
#!/bin/sh
# git-mergetool--lib is a library for common merge tool functions
diff_mode() {
test "$TOOL_MODE" = diff

View File

@@ -378,7 +378,7 @@ update_squash_messages () {
sed -e 1d -e '2,/^./{
/^$/d
}' <"$SQUASH_MSG".bak
} >$SQUASH_MSG
} >"$SQUASH_MSG"
else
commit_message HEAD > "$FIXUP_MSG" || die "Cannot write $FIXUP_MSG"
COUNT=2
@@ -387,7 +387,7 @@ update_squash_messages () {
echo "# The first commit's message is:"
echo
cat "$FIXUP_MSG"
} >$SQUASH_MSG
} >"$SQUASH_MSG"
fi
case $1 in
squash)
@@ -403,11 +403,11 @@ update_squash_messages () {
echo
commit_message $2 | sed -e 's/^/# /'
;;
esac >>$SQUASH_MSG
esac >>"$SQUASH_MSG"
}
peek_next_command () {
sed -n -e "/^#/d" -e "/^$/d" -e "s/ .*//p" -e "q" < "$TODO"
sed -n -e "/^#/d" -e '/^$/d' -e "s/ .*//p" -e "q" < "$TODO"
}
# A squash/fixup has failed. Prepare the long version of the squash

View File

@@ -85,10 +85,8 @@ continue_merge () {
printf "Already applied: %0${prec}d " $msgnum
fi
fi
if test -z "$GIT_QUIET"
then
git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
fi
test -z "$GIT_QUIET" &&
GIT_PAGER='' git log --format=%s -1 "$cmt"
prev_head=`git rev-parse HEAD^0`
# save the resulting commit so we can read-tree on it later

View File

@@ -26,6 +26,7 @@ if (! exists $ENV{SVN_SSH}) {
$ENV{SVN_SSH} = $ENV{GIT_SSH};
if ($^O eq 'msys') {
$ENV{SVN_SSH} =~ s/\\/\\\\/g;
$ENV{SVN_SSH} =~ s/(.*)/"$1"/;
}
}
}

View File

@@ -98,6 +98,7 @@ BuildRequires: perl(Error)
Perl interface to Git
%define path_settings ETC_GITCONFIG=/etc/gitconfig prefix=%{_prefix} mandir=%{_mandir} htmldir=%{_docdir}/%{name}-%{version}
%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
%prep
%setup -q
@@ -112,6 +113,7 @@ rm -rf $RPM_BUILD_ROOT
make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \
%{path_settings} \
INSTALLDIRS=vendor install %{!?_without_docs: install-doc}
test ! -d $RPM_BUILD_ROOT%{python_sitelib} || rm -fr $RPM_BUILD_ROOT%{python_sitelib}
find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
@@ -190,6 +192,12 @@ rm -rf $RPM_BUILD_ROOT
# No files for you!
%changelog
* Sun Jan 31 2010 Junio C Hamano <gitster@pobox.com>
- Do not use %define inside %{!?...} construct.
* Sat Jan 30 2010 Junio C Hamano <gitster@pobox.com>
- We don't ship Python bits until a real foreign scm interface comes.
* Mon Feb 04 2009 David J. Mellor <dmellor@whistlingcat.com>
- fixed broken git help -w after renaming the git-core package to git.

View File

@@ -130,7 +130,7 @@ proc unmerged_files {files} {
}
proc parseviewargs {n arglist} {
global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs
global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
set vdatemode($n) 0
set vmergeonly($n) 0
@@ -210,6 +210,9 @@ proc parseviewargs {n arglist} {
# git rev-parse doesn't understand --merge
lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
}
"--no-replace-objects" {
set env(GIT_NO_REPLACE_OBJECTS) "1"
}
"-*" {
# Other flag arguments including -<n>
if {[string is digit -strict [string range $arg 1 end]]} {
@@ -2085,7 +2088,7 @@ proc makewindow {} {
set sha1entry .tf.bar.sha1
set entries $sha1entry
set sha1but .tf.bar.sha1label
button $sha1but -text [mc "SHA1 ID: "] -state disabled -relief flat \
button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
-command gotocommit -width 8
$sha1but conf -disabledforeground [$sha1but cget -foreground]
pack .tf.bar.sha1label -side left
@@ -7687,8 +7690,10 @@ proc getblobdiffline {bdf ids} {
makediffhdr $fname $ids
$ctext insert end "\n$line\n" filesep
} elseif {![string compare -length 3 " >" $line]} {
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" dresult
} elseif {![string compare -length 3 " <" $line]} {
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" d0
} elseif {$diffinhdr} {
if {![string compare -length 12 "rename from " $line]} {
@@ -8699,6 +8704,11 @@ proc mktag {} {
${NS}::label $top.tlab -text [mc "Tag name:"]
${NS}::entry $top.tag -width 60
grid $top.tlab $top.tag -sticky w
${NS}::label $top.op -text [mc "Tag message is optional"]
grid $top.op -columnspan 2 -sticky we
${NS}::label $top.mlab -text [mc "Tag message:"]
${NS}::entry $top.msg -width 60
grid $top.mlab $top.msg -sticky w
${NS}::frame $top.buts
${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
@@ -8716,6 +8726,7 @@ proc domktag {} {
set id [$mktagtop.sha1 get]
set tag [$mktagtop.tag get]
set msg [$mktagtop.msg get]
if {$tag == {}} {
error_popup [mc "No tag name specified"] $mktagtop
return 0
@@ -8725,7 +8736,11 @@ proc domktag {} {
return 0
}
if {[catch {
exec git tag $tag $id
if {$msg != {}} {
exec git tag -a -m $msg $tag $id
} else {
exec git tag $tag $id
}
} err]} {
error_popup "[mc "Error creating tag:"] $err" $mktagtop
return 0
@@ -10481,7 +10496,7 @@ proc showtag {tag isnew} {
set linknum 0
if {![info exists tagcontents($tag)]} {
catch {
set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
set tagcontents($tag) [exec git cat-file tag $tag]
}
}
if {[info exists tagcontents($tag)]} {

File diff suppressed because it is too large Load Diff

1254
gitk-git/po/fr.po Normal file

File diff suppressed because it is too large Load Diff

1295
gitk-git/po/hu.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

115
grep.c
View File

@@ -29,6 +29,28 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
p->next = NULL;
}
struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
{
struct grep_pat *pat;
struct grep_opt *ret = xmalloc(sizeof(struct grep_opt));
*ret = *opt;
ret->pattern_list = NULL;
ret->pattern_tail = &ret->pattern_list;
for(pat = opt->pattern_list; pat != NULL; pat = pat->next)
{
if(pat->token == GREP_PATTERN_HEAD)
append_header_grep_pattern(ret, pat->field,
pat->pattern);
else
append_grep_pattern(ret, pat->pattern, pat->origin,
pat->no, pat->token);
}
return ret;
}
static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
{
int err;
@@ -253,7 +275,8 @@ static int word_char(char ch)
static void show_name(struct grep_opt *opt, const char *name)
{
printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
opt->output(opt, name, strlen(name));
opt->output(opt, opt->null_following_name ? "\0" : "\n", 1);
}
@@ -490,24 +513,32 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
const char *name, unsigned lno, char sign)
{
int rest = eol - bol;
char sign_str[1];
sign_str[0] = sign;
if (opt->pre_context || opt->post_context) {
if (opt->last_shown == 0) {
if (opt->show_hunk_mark)
fputs("--\n", stdout);
opt->output(opt, "--\n", 3);
else
opt->show_hunk_mark = 1;
} else if (lno > opt->last_shown + 1)
fputs("--\n", stdout);
opt->output(opt, "--\n", 3);
}
opt->last_shown = lno;
if (opt->null_following_name)
sign = '\0';
if (opt->pathname)
printf("%s%c", name, sign);
if (opt->linenum)
printf("%d%c", lno, sign);
sign_str[0] = '\0';
if (opt->pathname) {
opt->output(opt, name, strlen(name));
opt->output(opt, sign_str, 1);
}
if (opt->linenum) {
char buf[32];
snprintf(buf, sizeof(buf), "%d", lno);
opt->output(opt, buf, strlen(buf));
opt->output(opt, sign_str, 1);
}
if (opt->color) {
regmatch_t match;
enum grep_context ctx = GREP_CONTEXT_BODY;
@@ -518,18 +549,22 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
while (next_match(opt, bol, eol, ctx, &match, eflags)) {
if (match.rm_so == match.rm_eo)
break;
printf("%.*s%s%.*s%s",
(int)match.rm_so, bol,
opt->color_match,
(int)(match.rm_eo - match.rm_so), bol + match.rm_so,
GIT_COLOR_RESET);
opt->output(opt, bol, match.rm_so);
opt->output(opt, opt->color_match,
strlen(opt->color_match));
opt->output(opt, bol + match.rm_so,
(int)(match.rm_eo - match.rm_so));
opt->output(opt, GIT_COLOR_RESET,
strlen(GIT_COLOR_RESET));
bol += match.rm_eo;
rest -= match.rm_eo;
eflags = REG_NOTBOL;
}
*eol = ch;
}
printf("%.*s\n", rest, bol);
opt->output(opt, bol, rest);
opt->output(opt, "\n", 1);
}
static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
@@ -640,8 +675,15 @@ static int look_ahead(struct grep_opt *opt,
if (p->fixed)
hit = !fixmatch(p->pattern, bol, p->ignore_case, &m);
else
else {
#ifdef REG_STARTEND
m.rm_so = 0;
m.rm_eo = *left_p;
hit = !regexec(&p->regexp, bol, 1, &m, REG_STARTEND);
#else
hit = !regexec(&p->regexp, bol, 1, &m, 0);
#endif
}
if (!hit || m.rm_so < 0 || m.rm_eo < 0)
continue;
if (earliest < 0 || m.rm_so < earliest)
@@ -667,6 +709,32 @@ static int look_ahead(struct grep_opt *opt,
return 0;
}
int grep_threads_ok(const struct grep_opt *opt)
{
/* If this condition is true, then we may use the attribute
* machinery in grep_buffer_1. The attribute code is not
* thread safe, so we disable the use of threads.
*/
if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
!opt->name_only)
return 0;
/* If we are showing hunk marks, we should not do it for the
* first match. The synchronization problem we get for this
* constraint is not yet solved, so we disable threading in
* this case.
*/
if (opt->pre_context || opt->post_context)
return 0;
return 1;
}
static void std_output(struct grep_opt *opt, const void *buf, size_t size)
{
fwrite(buf, size, 1, stdout);
}
static int grep_buffer_1(struct grep_opt *opt, const char *name,
char *buf, unsigned long size, int collect_hits)
{
@@ -682,6 +750,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
opt->last_shown = 0;
if (!opt->output)
opt->output = std_output;
if (buffer_is_binary(buf, size)) {
switch (opt->binary) {
case GREP_BINARY_DEFAULT:
@@ -754,7 +825,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
if (opt->status_only)
return 1;
if (binary_match_only) {
printf("Binary file %s matches\n", name);
opt->output(opt, "Binary file ", 12);
opt->output(opt, name, strlen(name));
opt->output(opt, " matches\n", 9);
return 1;
}
if (opt->name_only) {
@@ -810,9 +883,13 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
* which feels mostly useless but sometimes useful. Maybe
* make it another option? For now suppress them.
*/
if (opt->count && count)
printf("%s%c%u\n", name,
opt->null_following_name ? '\0' : ':', count);
if (opt->count && count) {
char buf[32];
opt->output(opt, name, strlen(name));
snprintf(buf, sizeof(buf), "%c%u\n",
opt->null_following_name ? '\0' : ':', count);
opt->output(opt, buf, strlen(buf));
}
return !!last_hit;
}

6
grep.h
View File

@@ -91,6 +91,9 @@ struct grep_opt {
unsigned last_shown;
int show_hunk_mark;
void *priv;
void (*output)(struct grep_opt *opt, const void *data, size_t size);
void *output_priv;
};
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
@@ -99,4 +102,7 @@ extern void compile_grep_patterns(struct grep_opt *opt);
extern void free_grep_patterns(struct grep_opt *opt);
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
extern int grep_threads_ok(const struct grep_opt *opt);
#endif

View File

@@ -33,8 +33,7 @@ void *patch_delta(const void *src_buf, unsigned long src_size,
/* now the result size */
size = get_delta_hdr_size(&data, top);
dst_buf = xmalloc(size + 1);
dst_buf[size] = 0;
dst_buf = xmallocz(size);
out = dst_buf;
while (data < top) {

View File

@@ -47,6 +47,8 @@ static void *preload_thread(void *_data)
if (ce_stage(ce))
continue;
if (S_ISGITLINK(ce->ce_mode))
continue;
if (ce_uptodate(ce))
continue;
if (!ce_path_match(ce, p->pathspec))

View File

@@ -612,7 +612,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
if (alias && !ce_stage(alias) && !ie_match_stat(istate, alias, st, ce_option)) {
/* Nothing changed, really */
free(ce);
ce_mark_uptodate(alias);
if (!S_ISGITLINK(alias->ce_mode))
ce_mark_uptodate(alias);
alias->ce_flags |= CE_ADDED;
return 0;
}
@@ -1050,7 +1051,8 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
* because CE_UPTODATE flag is in-core only;
* we are not going to write this change out.
*/
ce_mark_uptodate(ce);
if (!S_ISGITLINK(ce->ce_mode))
ce_mark_uptodate(ce);
return ce;
}
}

View File

@@ -325,7 +325,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
for (i = 0; i < 3; i++)
free(mmfile[i].ptr);
memset(&io, 0, sizeof(&io));
memset(&io, 0, sizeof(io));
io.io.getline = rerere_mem_getline;
if (output)
io.io.output = fopen(output, "w");

View File

@@ -134,10 +134,20 @@ static void add_pending_object_with_mode(struct rev_info *revs, struct object *o
{
if (revs->no_walk && (obj->flags & UNINTERESTING))
revs->no_walk = 0;
if (revs->reflog_info && obj->type == OBJ_COMMIT &&
add_reflog_for_walk(revs->reflog_info,
(struct commit *)obj, name))
return;
if (revs->reflog_info && obj->type == OBJ_COMMIT) {
struct strbuf buf = STRBUF_INIT;
int len = interpret_branch_name(name, &buf);
int st;
if (0 < len && name[len] && buf.len)
strbuf_addstr(&buf, name + len);
st = add_reflog_for_walk(revs->reflog_info,
(struct commit *)obj,
buf.buf[0] ? buf.buf: name);
strbuf_release(&buf);
if (st)
return;
}
add_object_array_with_mode(obj, name, &revs->pending, mode);
}

View File

@@ -1166,7 +1166,7 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
{
int bytes = strlen(buffer) + 1;
unsigned char *buf = xmalloc(1+size);
unsigned char *buf = xmallocz(size);
unsigned long n;
int status = Z_OK;
@@ -1194,7 +1194,6 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size
while (status == Z_OK)
status = git_inflate(stream, Z_FINISH);
}
buf[size] = 0;
if (status == Z_STREAM_END && !stream->avail_in) {
git_inflate_end(stream);
return buf;
@@ -1517,8 +1516,7 @@ static void *unpack_compressed_entry(struct packed_git *p,
z_stream stream;
unsigned char *buffer, *in;
buffer = xmalloc(size + 1);
buffer[size] = 0;
buffer = xmallocz(size);
memset(&stream, 0, sizeof(stream));
stream.next_out = buffer;
stream.avail_out = size + 1;

View File

@@ -399,6 +399,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
unsigned long co_time;
int co_tz, co_cnt;
/* a @{-N} placed anywhere except the start is an error */
if (str[at+2] == '-')
return -1;
/* Is it asking for N-th entry, or approxidate? */
for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
char ch = str[at+2+i];
@@ -413,9 +417,12 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
} else if (0 <= nth)
at_time = 0;
else {
int errors = 0;
char *tmp = xstrndup(str + at + 2, reflog_len);
at_time = approxidate(tmp);
at_time = approxidate_careful(tmp, &errors);
free(tmp);
if (errors)
return -1;
}
if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
&co_time, &co_tz, &co_cnt)) {
@@ -878,8 +885,28 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
if (!len)
return len; /* syntax Ok, not enough switches */
if (0 < len)
return len; /* consumed from the front */
if (0 < len && len == namelen)
return len; /* consumed all */
else if (0 < len) {
/* we have extra data, which might need further processing */
struct strbuf tmp = STRBUF_INIT;
int used = buf->len;
int ret;
strbuf_add(buf, name + len, namelen - len);
ret = interpret_branch_name(buf->buf, &tmp);
/* that data was not interpreted, remove our cruft */
if (ret < 0) {
strbuf_setlen(buf, used);
return len;
}
strbuf_reset(buf);
strbuf_addbuf(buf, &tmp);
strbuf_release(&tmp);
/* tweak for size of {-N} versus expanded ref name */
return ret - used + len;
}
cp = strchr(name, '@');
if (!cp)
return -1;

View File

@@ -10,17 +10,19 @@ static int add_submodule_odb(const char *path)
{
struct strbuf objects_directory = STRBUF_INIT;
struct alternate_object_database *alt_odb;
int ret = 0;
strbuf_addf(&objects_directory, "%s/.git/objects/", path);
if (!is_directory(objects_directory.buf))
return -1;
if (!is_directory(objects_directory.buf)) {
ret = -1;
goto done;
}
/* avoid adding it twice */
for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
if (alt_odb->name - alt_odb->base == objects_directory.len &&
!strncmp(alt_odb->base, objects_directory.buf,
objects_directory.len))
return 0;
goto done;
alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
alt_odb->next = alt_odb_list;
@@ -31,11 +33,14 @@ static int add_submodule_odb(const char *path)
alt_odb->name[41] = '\0';
alt_odb_list = alt_odb;
prepare_alt_odb();
return 0;
done:
strbuf_release(&objects_directory);
return ret;
}
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
const char *del, const char *add, const char *reset)
{
struct rev_info rev;
@@ -85,6 +90,8 @@ void show_submodule_summary(FILE *f, const char *path,
if (!fast_backward && !fast_forward)
strbuf_addch(&sb, '.');
strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
if (dirty_submodule)
strbuf_add(&sb, "-dirty", 6);
if (message)
strbuf_addf(&sb, " %s\n", message);
else
@@ -123,7 +130,7 @@ int is_submodule_modified(const char *path)
"--porcelain",
NULL,
};
char *env[3];
char *env[4];
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%s/.git/", path);
@@ -139,7 +146,9 @@ int is_submodule_modified(const char *path)
env[0] = strbuf_detach(&buf, NULL);
strbuf_addf(&buf, "GIT_DIR=%s/.git", path);
env[1] = strbuf_detach(&buf, NULL);
env[2] = NULL;
strbuf_addf(&buf, "GIT_INDEX_FILE");
env[2] = strbuf_detach(&buf, NULL);
env[3] = NULL;
memset(&cp, 0, sizeof(cp));
cp.argv = argv;
@@ -158,6 +167,7 @@ int is_submodule_modified(const char *path)
free(env[0]);
free(env[1]);
free(env[2]);
strbuf_release(&buf);
return len != 0;
}

View File

@@ -3,6 +3,7 @@
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
const char *del, const char *add, const char *reset);
int is_submodule_modified(const char *path);

View File

@@ -4,21 +4,8 @@ test_description='CRLF conversion'
. ./test-lib.sh
q_to_nul () {
perl -pe 'y/Q/\000/'
}
q_to_cr () {
tr Q '\015'
}
append_cr () {
sed -e 's/$/Q/' | tr Q '\015'
}
remove_cr () {
tr '\015' Q <"$1" | grep Q >/dev/null &&
tr '\015' Q <"$1" | sed -ne 's/Q$//p'
has_cr() {
tr '\015' Q <"$1" | grep Q >/dev/null
}
test_expect_success setup '
@@ -156,7 +143,7 @@ test_expect_success 'checkout with autocrlf=true' '
for f in one dir/two
do
remove_cr "$f" >tmp && mv -f tmp $f &&
remove_cr <"$f" >tmp && mv -f tmp $f &&
git update-index -- $f || {
echo "Eh? $f"
false
@@ -180,7 +167,7 @@ test_expect_success 'checkout with autocrlf=input' '
for f in one dir/two
do
if remove_cr "$f" >/dev/null
if has_cr "$f"
then
echo "Eh? $f"
false
@@ -245,7 +232,7 @@ test_expect_success 'apply patch (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
test "$patched" = "`remove_cr <one | git hash-object --stdin`" || {
echo "Eh? apply without index"
false
}
@@ -272,7 +259,7 @@ test_expect_success 'apply patch --index (autocrlf=true)' '
git apply --index patch.file &&
test "$patched" = `git rev-parse :one` &&
test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
test "$patched" = "`remove_cr <one | git hash-object --stdin`" || {
echo "Eh? apply with --index"
false
}
@@ -285,7 +272,7 @@ test_expect_success '.gitattributes says two is binary' '
git config core.autocrlf true &&
git read-tree --reset -u HEAD &&
if remove_cr dir/two >/dev/null
if has_cr dir/two
then
echo "Huh?"
false
@@ -293,7 +280,7 @@ test_expect_success '.gitattributes says two is binary' '
: happy
fi &&
if remove_cr one >/dev/null
if has_cr one
then
: happy
else
@@ -301,7 +288,7 @@ test_expect_success '.gitattributes says two is binary' '
false
fi &&
if remove_cr three >/dev/null
if has_cr three
then
echo "Huh?"
false
@@ -316,7 +303,7 @@ test_expect_success '.gitattributes says two is input' '
echo "two crlf=input" >.gitattributes &&
git read-tree --reset -u HEAD &&
if remove_cr dir/two >/dev/null
if has_cr dir/two
then
echo "Huh?"
false
@@ -331,7 +318,7 @@ test_expect_success '.gitattributes says two and three are text' '
echo "t* crlf" >.gitattributes &&
git read-tree --reset -u HEAD &&
if remove_cr dir/two >/dev/null
if has_cr dir/two
then
: happy
else
@@ -339,7 +326,7 @@ test_expect_success '.gitattributes says two and three are text' '
false
fi &&
if remove_cr three >/dev/null
if has_cr three
then
: happy
else
@@ -357,14 +344,14 @@ test_expect_success 'in-tree .gitattributes (1)' '
rm -rf tmp one dir .gitattributes patch.file three &&
git read-tree --reset -u HEAD &&
if remove_cr one >/dev/null
if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
remove_cr three >/dev/null || {
has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -376,14 +363,14 @@ test_expect_success 'in-tree .gitattributes (2)' '
git read-tree --reset HEAD &&
git checkout-index -f -q -u -a &&
if remove_cr one >/dev/null
if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
remove_cr three >/dev/null || {
has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -396,14 +383,14 @@ test_expect_success 'in-tree .gitattributes (3)' '
git checkout-index -u .gitattributes &&
git checkout-index -u one dir/two three &&
if remove_cr one >/dev/null
if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
remove_cr three >/dev/null || {
has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -416,14 +403,14 @@ test_expect_success 'in-tree .gitattributes (4)' '
git checkout-index -u one dir/two three &&
git checkout-index -u .gitattributes &&
if remove_cr one >/dev/null
if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
remove_cr three >/dev/null || {
has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -456,7 +443,7 @@ test_expect_success 'checkout when deleting .gitattributes' '
git checkout master~1 &&
git checkout master &&
remove_cr .file2 >/dev/null
has_cr .file2
'

View File

@@ -12,7 +12,7 @@ test_expect_success setup '
test_tick &&
git commit -m Initial &&
sed -e "s/\$/
append_cr <"$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas &&
git add elpmas &&
rm -f sample &&

45
t/t0101-at-syntax.sh Executable file
View File

@@ -0,0 +1,45 @@
#!/bin/sh
test_description='various @{whatever} syntax tests'
. ./test-lib.sh
test_expect_success 'setup' '
test_commit one &&
test_commit two
'
check_at() {
echo "$2" >expect &&
git log -1 --format=%s "$1" >actual &&
test_cmp expect actual
}
test_expect_success '@{0} shows current' '
check_at @{0} two
'
test_expect_success '@{1} shows old' '
check_at @{1} one
'
test_expect_success '@{now} shows current' '
check_at @{now} two
'
test_expect_success '@{2001-09-17} (before the first commit) shows old' '
check_at @{2001-09-17} one
'
test_expect_success 'silly approxidates work' '
check_at @{3.hot.dogs.on.2001-09-17} one
'
test_expect_success 'notice misspelled upstream' '
test_must_fail git log -1 --format=%s @{usptream}
'
test_expect_success 'complain about total nonsense' '
test_must_fail git log -1 --format=%s @{utter.bogosity}
'
test_done

View File

@@ -398,6 +398,17 @@ test_expect_success 'alternative GIT_CONFIG' 'cmp output expect'
test_expect_success 'alternative GIT_CONFIG (--file)' \
'git config --file other-config -l > output && cmp output expect'
test_expect_success 'refer config from subdirectory' '
mkdir x &&
(
cd x &&
echo strasse >expect
git config --get --file ../other-config ein.bahn >actual &&
test_cmp expect actual
)
'
GIT_CONFIG=other-config git config anwohner.park ausweis
cat > expect << EOF

View File

@@ -107,4 +107,33 @@ test_expect_success 'checkout other@{u}' '
test_cmp expect actual
'
cat >expect <<EOF
commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
Reflog: master@{0} (C O Mitter <committer@example.com>)
Reflog message: branch: Created from HEAD
Author: A U Thor <author@example.com>
Date: Thu Apr 7 15:15:13 2005 -0700
3
EOF
test_expect_success 'log -g other@{u}' '
git log -1 -g other@{u} >actual &&
test_cmp expect actual
'
cat >expect <<EOF
commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>)
Reflog message: branch: Created from HEAD
Author: A U Thor <author@example.com>
Date: Thu Apr 7 15:15:13 2005 -0700
3
EOF
test_expect_success 'log -g other@{u}@{now}' '
git log -1 -g other@{u}@{now} >actual &&
test_cmp expect actual
'
test_done

51
t/t1508-at-combinations.sh Executable file
View File

@@ -0,0 +1,51 @@
#!/bin/sh
test_description='test various @{X} syntax combinations together'
. ./test-lib.sh
check() {
test_expect_${3:-success} "$1 = $2" "
echo '$2' >expect &&
git log -1 --format=%s '$1' >actual &&
test_cmp expect actual
"
}
nonsense() {
test_expect_${2:-success} "$1 is nonsensical" "
test_must_fail git log -1 '$1'
"
}
fail() {
"$@" failure
}
test_expect_success 'setup' '
test_commit master-one &&
test_commit master-two &&
git checkout -b upstream-branch &&
test_commit upstream-one &&
test_commit upstream-two &&
git checkout -b old-branch &&
test_commit old-one &&
test_commit old-two &&
git checkout -b new-branch &&
test_commit new-one &&
test_commit new-two &&
git config branch.old-branch.remote . &&
git config branch.old-branch.merge refs/heads/master &&
git config branch.new-branch.remote . &&
git config branch.new-branch.merge refs/heads/upstream-branch
'
check HEAD new-two
check "@{1}" new-one
check "@{-1}" old-two
check "@{-1}@{1}" old-one
check "@{u}" upstream-two
check "@{u}@{1}" upstream-one
check "@{-1}@{u}" master-two
check "@{-1}@{u}@{1}" master-one
nonsense "@{u}@{-1}"
nonsense "@{1}@{u}"
test_done

View File

@@ -134,10 +134,6 @@ test_expect_success 'rebase -q is quiet' '
test ! -s output.out
'
q_to_cr () {
tr Q '\015'
}
test_expect_success 'Rebase a commit that sprinkles CRs in' '
(
echo "One"

View File

@@ -32,8 +32,8 @@ test_expect_success rebase '
git checkout side &&
git rebase master &&
git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
git cat-file commit side@{1} | sed -e "1,/^$/d" >expect &&
git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
git cat-file commit side@{1} | sed -e "1,/^\$/d" >expect &&
test_cmp expect actual
'

View File

@@ -77,10 +77,6 @@ test_expect_success 'apply binary patch' \
tree1=`git write-tree` &&
test "$tree1" = "$tree0"'
q_to_nul() {
perl -pe 'y/Q/\000/'
}
nul_to_q() {
perl -pe 'y/\000/Q/'
}

View File

@@ -93,9 +93,9 @@ test_expect_success 'extra headers' '
git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
" &&
git format-patch --stdout master..side > patch2 &&
sed -e "/^$/q" patch2 > hdrs2 &&
grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
sed -e "/^\$/q" patch2 > hdrs2 &&
grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
'
@@ -104,9 +104,9 @@ test_expect_success 'extra headers without newlines' '
git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
git format-patch --stdout master..side >patch3 &&
sed -e "/^$/q" patch3 > hdrs3 &&
grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
sed -e "/^\$/q" patch3 > hdrs3 &&
grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
'
@@ -115,32 +115,32 @@ test_expect_success 'extra headers with multiple To:s' '
git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
git format-patch --stdout master..side > patch4 &&
sed -e "/^$/q" patch4 > hdrs4 &&
grep "^To: R. E. Cipient <rcipient@example.com>,$" hdrs4 &&
grep "^ *S. E. Cipient <scipient@example.com>$" hdrs4
sed -e "/^\$/q" patch4 > hdrs4 &&
grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
'
test_expect_success 'additional command line cc' '
git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch5 &&
grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch5 &&
grep "^ *S. E. Cipient <scipient@example.com>$" patch5
git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
'
test_expect_success 'command line headers' '
git config --unset-all format.headers &&
git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch6 &&
grep "^Cc: R. E. Cipient <rcipient@example.com>$" patch6
git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
'
test_expect_success 'configuration headers and command line headers' '
git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch7 &&
grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch7 &&
grep "^ *S. E. Cipient <scipient@example.com>$" patch7
git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
'
test_expect_success 'multiple files' '
@@ -406,9 +406,9 @@ test_expect_success 'cover-letter inherits diff options' '
git mv file foo &&
git commit -m foo &&
git format-patch --cover-letter -1 &&
! grep "file => foo .* 0 *$" 0000-cover-letter.patch &&
! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
git format-patch --cover-letter -1 -M &&
grep "file => foo .* 0 *$" 0000-cover-letter.patch
grep "file => foo .* 0 *\$" 0000-cover-letter.patch
'
@@ -425,7 +425,7 @@ EOF
test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
git format-patch --cover-letter -2 &&
sed -e "1,/A U Thor/d" -e "/^$/q" < 0000-cover-letter.patch > output &&
sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
test_cmp expect output
'
@@ -450,7 +450,7 @@ EOF
test_expect_success 'format-patch respects -U' '
git format-patch -U4 -2 &&
sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
test_cmp expect output
'
@@ -471,7 +471,7 @@ EOF
test_expect_success 'format-patch -p suppresses stat' '
git format-patch -p -2 &&
sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
test_cmp expect output
'

View File

@@ -76,7 +76,7 @@ test_expect_success 'check combined output (1)' '
verify_helper sidewithone
'
test_expect_failure 'check combined output (2)' '
test_expect_success 'check combined output (2)' '
git show sidesansone -- >sidesansone &&
verify_helper sidesansone
'

View File

@@ -191,6 +191,73 @@ EOF
"
commit_file sm1 &&
test_expect_success 'submodule is up to date' "
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
EOF
"
test_expect_success 'submodule contains untracked content' "
echo new > sm1/new-file &&
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head6-dirty:
EOF
"
test_expect_success 'submodule contains untracked and modifed content' "
echo new > sm1/foo6 &&
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head6-dirty:
EOF
"
test_expect_success 'submodule contains modifed content' "
rm -f sm1/new-file &&
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head6-dirty:
EOF
"
(cd sm1; git commit -mchange foo6 >/dev/null) &&
head8=$(cd sm1; git rev-parse --verify HEAD | cut -c1-7) &&
test_expect_success 'submodule is modified' "
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head8:
> change
EOF
"
test_expect_success 'modified submodule contains untracked content' "
echo new > sm1/new-file &&
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head8-dirty:
> change
EOF
"
test_expect_success 'modified submodule contains untracked and modifed content' "
echo modification >> sm1/foo6 &&
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head8-dirty:
> change
EOF
"
test_expect_success 'modified submodule contains modifed content' "
rm -f sm1/new-file &&
git diff-index -p --submodule=log HEAD >actual &&
diff actual - <<-EOF
Submodule sm1 $head6..$head8-dirty:
> change
EOF
"
rm -rf sm1
test_expect_success 'deleted submodule' "
git diff-index -p --submodule=log HEAD >actual &&

View File

@@ -37,11 +37,11 @@ test_expect_success setup '
# patch-2 is the same as patch-1 but is based
# on a version that already has whitespace fixed,
# and does not introduce whitespace breakages.
sed -e "s/ $//" patch-1 >patch-2 &&
sed -e "s/ \$//" patch-1 >patch-2 &&
# If all whitespace breakages are fixed the contents
# should look like file-fixed
sed -e "s/ $//" file-1 >file-fixed
sed -e "s/ \$//" file-1 >file-fixed
'

View File

@@ -83,6 +83,12 @@ test_expect_success setup '
echo "X-Fake-Field: Line Three" &&
git format-patch --stdout first | sed -e "1d"
} > patch1.eml &&
{
echo "X-Fake-Field: Line One" &&
echo "X-Fake-Field: Line Two" &&
echo "X-Fake-Field: Line Three" &&
git format-patch --stdout first | sed -e "1d"
} | append_cr >patch1-crlf.eml &&
sed -n -e "3,\$p" msg >file &&
git add file &&
test_tick &&
@@ -123,6 +129,15 @@ test_expect_success 'am applies patch e-mail not in a mbox' '
test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
'
test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
git checkout first &&
git am patch1-crlf.eml &&
! test -d .git/rebase-apply &&
test -z "$(git diff second)" &&
test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
'
GIT_AUTHOR_NAME="Another Thor"
GIT_AUTHOR_EMAIL="a.thor@example.com"
GIT_COMMITTER_NAME="Co M Miter"
@@ -291,7 +306,7 @@ test_expect_success 'am --committer-date-is-author-date' '
git checkout first &&
test_tick &&
git am --committer-date-is-author-date patch1 &&
git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
at=$(sed -ne "/^author /s/.*> //p" head1) &&
ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
test "$at" = "$ct"
@@ -301,7 +316,7 @@ test_expect_success 'am without --committer-date-is-author-date' '
git checkout first &&
test_tick &&
git am patch1 &&
git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
at=$(sed -ne "/^author /s/.*> //p" head1) &&
ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
test "$at" != "$ct"
@@ -315,7 +330,7 @@ test_expect_success 'am --ignore-date' '
git checkout first &&
test_tick &&
git am --ignore-date patch1 &&
git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
at=$(sed -ne "/^author /s/.*> //p" head1) &&
echo "$at" | grep "+0000"
'

View File

@@ -255,7 +255,7 @@ EOF
test_expect_success 'log --graph with merge' '
git log --graph --date-order --pretty=tformat:%s |
sed "s/ *$//" >actual &&
sed "s/ *\$//" >actual &&
test_cmp expect actual
'
@@ -315,7 +315,7 @@ EOF
test_expect_success 'log --graph with full output' '
git log --graph --date-order --pretty=short |
git name-rev --name-only --stdin |
sed "s/Merge:.*/Merge: A B/;s/ *$//" >actual &&
sed "s/Merge:.*/Merge: A B/;s/ *\$//" >actual &&
test_cmp expect actual
'
@@ -383,7 +383,7 @@ EOF
test_expect_success 'log --graph with merge' '
git log --graph --date-order --pretty=tformat:%s |
sed "s/ *$//" >actual &&
sed "s/ *\$//" >actual &&
test_cmp expect actual
'

View File

@@ -105,10 +105,8 @@ test_expect_success 'non-fast-forward push show ref status' '
'
test_expect_success 'non-fast-forward push shows help message' '
grep \
"To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the '"'non-fast-forward'"'
section of '"'git push --help'"' for details." output
grep "To prevent you from losing history, non-fast-forward updates were rejected" \
output
'
test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
@@ -126,10 +124,8 @@ test_expect_success 'push fails for non-fast-forward refs unmatched by remote he
grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output &&
grep \
"To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the '"'non-fast-forward'"'
section of '"'git push --help'"' for details." output
grep "To prevent you from losing history, non-fast-forward updates were rejected" \
output
'
stop_httpd

View File

@@ -146,8 +146,8 @@ test_expect_success 'binary files cannot be merged' '
grep "Cannot merge binary files" merge.err
'
sed -e "s/deerit.$/deerit;/" -e "s/me;$/me./" < new5.txt > new6.txt
sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt
sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" < new5.txt > new6.txt
sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" < new5.txt > new7.txt
test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '

View File

@@ -1,13 +1,5 @@
#!/bin/sh
append_cr () {
sed -e 's/$/Q/' | tr Q '\015'
}
remove_cr () {
tr '\015' Q | sed -e 's/Q$//'
}
test_description='merge conflict in crlf repo
b---M

View File

@@ -48,7 +48,7 @@ test_expect_success 'setup for merge test' '
git tag baseline
'
test_expect_failure 'do not lose a/b-2/c/d in merge (resolve)' '
test_expect_success 'do not lose a/b-2/c/d in merge (resolve)' '
git reset --hard &&
git checkout baseline^0 &&
git merge -s resolve master &&

View File

@@ -291,6 +291,14 @@ y:y yy
z:zzz
EOF
test_expect_success 'grep -q, silently report matches' '
>empty &&
git grep -q mmap >actual &&
test_cmp empty actual &&
test_must_fail git grep -q qfwfq >actual &&
test_cmp empty actual
'
# Create 1024 file names that sort between "y" and "z" to make sure
# the two files are handled by different calls to an external grep.
# This depends on MAXARGS in builtin-grep.c being 1024 or less.

View File

@@ -150,7 +150,7 @@ EOF
test_expect_success '--signoff' '
echo "yet another content *narf*" >> foo &&
echo "zort" | git commit -s -F - foo &&
git cat-file commit HEAD | sed "1,/^$/d" > output &&
git cat-file commit HEAD | sed "1,/^\$/d" > output &&
test_cmp expect output
'

View File

@@ -186,8 +186,8 @@ test_expect_success 'Prompting works' '
--smtp-server="$(pwd)/fake.sendmail" \
$patches \
2>errors &&
grep "^From: Example <from@example.com>$" msgtxt1 &&
grep "^To: to@example.com$" msgtxt1
grep "^From: Example <from@example.com>\$" msgtxt1 &&
grep "^To: to@example.com\$" msgtxt1
'
test_expect_success 'cccmd works' '
@@ -236,7 +236,7 @@ test_expect_success 'Author From: in message body' '
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
$patches &&
sed "1,/^$/d" < msgtxt1 > msgbody1
sed "1,/^\$/d" < msgtxt1 > msgbody1
grep "From: A <author@example.com>" msgbody1
'
@@ -247,7 +247,7 @@ test_expect_success 'Author From: not in message body' '
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
$patches &&
sed "1,/^$/d" < msgtxt1 > msgbody1
sed "1,/^\$/d" < msgtxt1 > msgbody1
! grep "From: A <author@example.com>" msgbody1
'

View File

@@ -96,7 +96,7 @@ EOF
test_expect_success 'pserver authentication' \
'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'pserver authentication failure (non-anonymous user)' \
'if cat request-git | git-cvsserver pserver >log 2>&1
@@ -105,11 +105,11 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \
else
true
fi &&
sed -ne \$p log | grep "^I HATE YOU$"'
sed -ne \$p log | grep "^I HATE YOU\$"'
test_expect_success 'pserver authentication (login)' \
'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'pserver authentication failure (login/non-anonymous user)' \
'if cat login-git | git-cvsserver pserver >log 2>&1
@@ -118,7 +118,7 @@ test_expect_success 'pserver authentication failure (login/non-anonymous user)'
else
true
fi &&
sed -ne \$p log | grep "^I HATE YOU$"'
sed -ne \$p log | grep "^I HATE YOU\$"'
# misuse pserver authentication for testing of req_Root
@@ -156,7 +156,7 @@ test_expect_success 'req_Root failure (conflicting roots)' \
test_expect_success 'req_Root (strict paths)' \
'cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (strict-paths)' '
! cat request-anonymous |
@@ -165,7 +165,7 @@ test_expect_success 'req_Root failure (strict-paths)' '
test_expect_success 'req_Root (w/o strict-paths)' \
'cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (w/o strict-paths)' '
! cat request-anonymous |
@@ -183,7 +183,7 @@ EOF
test_expect_success 'req_Root (base-path)' \
'cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (base-path)' '
! cat request-anonymous |
@@ -194,14 +194,14 @@ GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1
test_expect_success 'req_Root (export-all)' \
'cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (export-all w/o whitelist)' \
'! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)'
test_expect_success 'req_Root (everything together)' \
'cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
sed -ne \$p log | grep "^I LOVE YOU\$"'
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1

View File

@@ -11,14 +11,6 @@ repository using cvs CLI client via git-cvsserver server'
. ./test-lib.sh
q_to_nul () {
perl -pe 'y/Q/\000/'
}
q_to_cr () {
tr Q '\015'
}
marked_as () {
foundEntry="$(grep "^/$2/" "$1/CVS/Entries")"
if [ x"$foundEntry" = x"" ] ; then

View File

@@ -230,6 +230,22 @@ test_decode_color () {
-e 's/.\[m/<RESET>/g'
}
q_to_nul () {
perl -pe 'y/Q/\000/'
}
q_to_cr () {
tr Q '\015'
}
append_cr () {
sed -e 's/$/Q/' | tr Q '\015'
}
remove_cr () {
tr '\015' Q | sed -e 's/Q$//'
}
test_tick () {
if test -z "${test_tick+set}"
then

View File

@@ -912,20 +912,19 @@ static int external_specification_len(const char *url)
struct transport *transport_get(struct remote *remote, const char *url)
{
const char *helper;
struct transport *ret = xcalloc(1, sizeof(*ret));
if (!remote)
die("No remote provided to transport_get()");
ret->remote = remote;
helper = remote->foreign_vcs;
if (!url && remote && remote->url)
if (!url && remote->url)
url = remote->url[0];
ret->url = url;
/* In case previous URL had helper forced, reset it. */
remote->foreign_vcs = NULL;
/* maybe it is a foreign URL? */
if (url) {
const char *p = url;
@@ -933,11 +932,11 @@ struct transport *transport_get(struct remote *remote, const char *url)
while (isalnum(*p))
p++;
if (!prefixcmp(p, "::"))
remote->foreign_vcs = xstrndup(url, p - url);
helper = xstrndup(url, p - url);
}
if (remote && remote->foreign_vcs) {
transport_helper_init(ret, remote->foreign_vcs);
if (helper) {
transport_helper_init(ret, helper);
} else if (!prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;

View File

@@ -34,6 +34,16 @@ void *xmalloc(size_t size)
return ret;
}
void *xmallocz(size_t size)
{
void *ret;
if (size + 1 < size)
die("Data too large to fit into virtual memory space.");
ret = xmalloc(size + 1);
((char*)ret)[size] = 0;
return ret;
}
/*
* xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
* "data" to the allocated memory, zero terminates the allocated memory,
@@ -42,10 +52,7 @@ void *xmalloc(size_t size)
*/
void *xmemdupz(const void *data, size_t len)
{
char *p = xmalloc(len + 1);
memcpy(p, data, len);
p[len] = '\0';
return p;
return memcpy(xmallocz(len), data, len);
}
char *xstrndup(const char *str, size_t len)