* general protection faults with "git grep" version 1.7.7.1
From: Markus Trippelsdorf @ 2011-10-24 20:11 UTC (permalink / raw)
To: git
Suddenly I'm getting strange protection faults when I run "git grep" on
the gcc tree:
git[4245] general protection ip:7f291f01461f sp:7fff5618a8b0 error:0 in libc-2.14.90.so[7f291ef9a000+15d000]
% gdb git
GNU gdb (Gentoo 7.3.1 p1) 7.3.1
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>...
Reading symbols from /usr/bin/git...done.
(gdb) run grep composite_pointer_type
Starting program: /usr/bin/git grep composite_pointer_type
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
[Thread debugging using libthread_db enabled]
[New Thread 0x7ffff7859700 (LWP 18367)]
[New Thread 0x7ffff7058700 (LWP 18368)]
[New Thread 0x7ffff6857700 (LWP 18369)]
[New Thread 0x7ffff6056700 (LWP 18370)]
[New Thread 0x7ffff5855700 (LWP 18371)]
[New Thread 0x7ffff5054700 (LWP 18372)]
[New Thread 0x7ffff4853700 (LWP 18373)]
[New Thread 0x7ffff4052700 (LWP 18374)]
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff7bbb600, bytes=21) at malloc.c:3463
3463 while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim))
(gdb) bt
#0 _int_malloc (av=0x7ffff7bbb600, bytes=21) at malloc.c:3463
#1 0x00007ffff78d7300 in __GI___libc_malloc (bytes=21) at malloc.c:2924
#2 0x00007ffff78dc692 in __GI___strdup (s=0x7ffff2665760 "gcc/ada/i-cexten.ads") at strdup.c:43
#3 0x00000000004d5069 in xstrdup (str=0x7ffff2665760 "gcc/ada/i-cexten.ads") at wrapper.c:23
#4 0x000000000042c448 in grep_file_async (filename=0x7ffff2665760 "gcc/ada/i-cexten.ads", name=0x59fee0 "gcc/ada/i-cexten.ads",
opt=<optimized out>) at builtin/grep.c:148
#5 grep_file (opt=0x7fffffffbfc0, filename=0x7ffff2665760 "gcc/ada/i-cexten.ads") at builtin/grep.c:459
#6 0x000000000042ddb0 in grep_cache (cached=0, pathspec=0x7fffffffbf70, opt=0x7fffffffbfc0) at builtin/grep.c:528
#7 cmd_grep (argc=<optimized out>, argv=0x7ffff2665760, prefix=0x0) at builtin/grep.c:1062
#8 0x00000000004045b0 in run_builtin (argv=0x7fffffffe110, argc=2, p=0x536ba0) at git.c:308
#9 handle_internal_command (argc=2, argv=0x7fffffffe110) at git.c:466
#10 0x00000000004047ac in run_argv (argv=0x7fffffffdfa0, argcp=0x7fffffffdfac) at git.c:512
#11 main (argc=2, argv=0x7fffffffe110) at git.c:585
(gdb)
or:
% git grep composite_pointer_type
*** glibc detected *** git: double free or corruption (fasttop): 0x0000000001919800 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x792b6)[0x7f6ad1d392b6]
git[0x42bebb]
/lib64/libpthread.so.0(+0x7c9e)[0x7f6ad202ec9e]
/lib64/libc.so.6(clone+0x6d)[0x7f6ad1d99b8d]
======= Memory map: ========
00400000-00536000 r-xp 00000000 08:12 2310166 /usr/bin/git
00536000-0053d000 rw-p 00136000 08:12 2310166 /usr/bin/git
0053d000-0058b000 rw-p 00000000 00:00 0
01906000-01927000 rw-p 00000000 00:00 0 [heap]
...
And strange output:
...
gcc/cp/typeck.c: result_type = composite_pointer_type (type0, type1, op0, op1,
gcc/cp/typeck.c: result_type = composite_pointer_type (type0, type1, op0, op1,
error: 'gcc/testsuite/ada/acats/tests/c5/c54a24a.ada': short read No such file or directory
error: 'gcc/testsuite/ada/acats/tests/c5/c54a13a.ada': short read No such file or directory
error: 'gcc/testsuite/ada/acats/tests/c6/c64104m.ada': short read No such file or directory
error: 'gcc/testsuite/ada/acats/tests/cd/cd7101f.dep': short read No such file or directory
error: 'gcc/testsuite/ada/acats/tests/ce/ce3904a.ada': short read No such file or directory
error: 'gcc/testsuite/g++.dg/abi/pr39188-3b.C': short read No such file or directory
error: '<90>Dz^A': short read Is a directory
Note that all the above files actually exist.
All of this started with version v1.7.7.1, which I installed today. I
never had any problems with git before.
Any ideas what might be going on?
--
Markus
^ permalink raw reply
* Re: [PATCH v0] fast-import: Add drop command
From: Sverre Rabbelier @ 2011-10-24 18:01 UTC (permalink / raw)
To: Vitor Antunes; +Cc: Dmitry Ivankov, Jonathan Nieder, git, David Barr
In-Reply-To: <CAOpHH-WxhvEP58KkGhnJbATbzU6PDBeQB1_fhbQ+0fzDXznaYw@mail.gmail.com>
Heya,
On Mon, Oct 24, 2011 at 18:37, Vitor Antunes <vitor.hda@gmail.com> wrote:
> This thread did not receive any updates for a long time.
> Could someone provide some feedback?
>
> Is this feasible? Does it make sense to add this command? If not, why?
I for one welcome our new branch deleting overlords :).
You mention that checkpointing solves some of the concerns raised by
others in this thread, would automatic checkpointing be way to make
sure everything is as it should be?
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [PATCH/WIP 00/11] read_directory() rewrite to support struct pathspec
From: Junio C Hamano @ 2011-10-24 17:10 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy; +Cc: git
In-Reply-To: <1319438176-7304-1-git-send-email-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> This is the first time "make test" fully passes (*) for me, so it's
> probably good enough for human eyes.
Nice way to describe the done-ness of the series. Looking forward to read
it through ;-)
Thanks.
^ permalink raw reply
* Re: [PATCH v0] fast-import: Add drop command
From: Vitor Antunes @ 2011-10-24 16:37 UTC (permalink / raw)
To: Dmitry Ivankov, Jonathan Nieder; +Cc: git, Sverre Rabbelier, David Barr
In-Reply-To: <CAOpHH-WSyD23GKtZ2nLiSsJfLU-+7ibyGhGccyvtAhKQ-jffBw@mail.gmail.com>
Hi,
This thread did not receive any updates for a long time.
Could someone provide some feedback?
Is this feasible? Does it make sense to add this command? If not, why?
Thanks,
Vitor
On Tue, Sep 27, 2011 at 9:57 AM, Vitor Antunes <vitor.hda@gmail.com> wrote:
> On Sat, Sep 24, 2011 at 10:19 PM, Dmitry Ivankov <divanorama@gmail.com> wrote:
>> On Sun, Sep 25, 2011 at 1:37 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:
>>> Thanks. I must have missed the earlier discussion. What are the
>>> semantics of this command and its intended purpose?
>> My guess is that if fast-import is used to manage a set of "remote"
>> branches, it should be able to delete branches. Then, it should
>> be allowed to do non-fastforward updates too (--force). Why can't
>> it just ignore branches deletion (considering --force)?
>
> I started by using --force, but I did not want to completely disable
> these checks. The idea of the drop command is to add support to the
> exceptions that require non-fastforward updates.
>
>> Random thoughts:
>> 1. once 'drop' is executed, fast-import can't tell if the branch was
>> actually deleted. And moreover any attempt to read this branch
>> head becomes illegal (either it's missing in .git or fast-import is
>> instructed to use a dropped branch).
>> 2. 'reset' command is a bit like proposed 'drop' but it never deletes
>> a branch ref. Consider following imports:
>> 1) import branch topic
>> 2) reset topic
>> 3) import branch topic2 starting at topic (incorrect import)
>> If 1-3) is done in one fast-import process, the error is reported.
>> If 3) is done separately, it succeeds but the result is strange:
>> topic2 isn't started from scratch but from old "erased" topic.
>> So, maybe, reset should be fixed to erase branches on --force.
>
> I think you are not considering the possibility that checkpoints could
> have been done along the way. I use them frequently to be able to
> analyse branches with diff-tree. As soon as a checkpoint is done,
> update-branches will issue an error (commit A is not part of branch A').
>
>> One more scenario is:
>> 1) import topic
>> 2) reset topic
>> 3) import topic
>> If 1-3) go together - no error
>> If 3) goes separate - no error, but non-fastforward update.
>> Much more harmless, but still may look strange.
>
> Not exactly true if there is a checkpoint done after step 1.
>
> My scenario is:
>
> 1) import topic
> 2) checkpoint
> 3) diff-tree and processing
> 4) exit if processing returns ok
> 5) reset topic to another HEAD
> 6) goto 1)
^ permalink raw reply
* [PATCH v4 3/3] upload-archive: use start_command instead of fork
From: Erik Faye-Lund @ 2011-10-24 16:02 UTC (permalink / raw)
To: git; +Cc: gitster, j6t, peff, rene.scharfe
In-Reply-To: <1319472131-3968-1-git-send-email-kusmabite@gmail.com>
The POSIX-function fork is not supported on Windows. Use our
start_command API instead.
As this is the last call-site that depends on the fork-stub in
compat/mingw.h, remove that as well.
Add an undocumented flag to git-archive that tells it that the
action originated from a remote, so features can be disabled.
Thanks to Jeff King for work on this part.
Remove the NOT_MINGW-prereq for t5000, as git-archive --remote
now works.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
Helped-by: Jeff King <peff@peff.net>
---
builtin/archive.c | 6 +++-
builtin/upload-archive.c | 68 ++++++++++++++-------------------------------
compat/mingw.h | 2 -
t/t5000-tar-tree.sh | 10 +++---
4 files changed, 31 insertions(+), 55 deletions(-)
diff --git a/builtin/archive.c b/builtin/archive.c
index 931956d..e405566 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -87,6 +87,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
const char *exec = "git-upload-archive";
const char *output = NULL;
const char *remote = NULL;
+ int is_remote = 0;
struct option local_opts[] = {
OPT_STRING('o', "output", &output, "file",
"write the archive to this file"),
@@ -94,6 +95,9 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
"retrieve the archive from remote repository <repo>"),
OPT_STRING(0, "exec", &exec, "cmd",
"path to the remote git-upload-archive command"),
+ { OPTION_BOOLEAN, 0, "remote-request", &is_remote, NULL,
+ "indicate we are serving a remote request",
+ PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
OPT_END()
};
@@ -108,5 +112,5 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
- return write_archive(argc, argv, prefix, 1, output, 0);
+ return write_archive(argc, argv, prefix, 1, output, is_remote);
}
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 2d0b383..c57e8bd 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -6,6 +6,7 @@
#include "archive.h"
#include "pkt-line.h"
#include "sideband.h"
+#include "run-command.h"
static const char upload_archive_usage[] =
"git upload-archive <repo>";
@@ -18,28 +19,17 @@ static const char lostchild[] =
#define MAX_ARGS (64)
-static int run_upload_archive(int argc, const char **argv, const char *prefix)
+static void prepare_argv(const char **sent_argv, const char **argv)
{
- const char *sent_argv[MAX_ARGS];
const char *arg_cmd = "argument ";
char *p, buf[4096];
int sent_argc;
int len;
- if (argc != 2)
- usage(upload_archive_usage);
-
- if (strlen(argv[1]) + 1 > sizeof(buf))
- die("insanely long repository name");
-
- strcpy(buf, argv[1]); /* enter-repo smudges its argument */
-
- if (!enter_repo(buf, 0))
- die("'%s' does not appear to be a git repository", buf);
-
/* put received options in sent_argv[] */
- sent_argc = 1;
- sent_argv[0] = "git-upload-archive";
+ sent_argc = 2;
+ sent_argv[0] = "archive";
+ sent_argv[1] = "--remote-request";
for (p = buf;;) {
/* This will die if not enough free space in buf */
len = packet_read_line(0, p, (buf + sizeof buf) - p);
@@ -62,9 +52,6 @@ static int run_upload_archive(int argc, const char **argv, const char *prefix)
*p++ = 0;
}
sent_argv[sent_argc] = NULL;
-
- /* parse all options sent by the client */
- return write_archive(sent_argc, sent_argv, prefix, 0, NULL, 1);
}
__attribute__((format (printf, 1, 2)))
@@ -96,38 +83,25 @@ static ssize_t process_input(int child_fd, int band)
int cmd_upload_archive(int argc, const char **argv, const char *prefix)
{
- pid_t writer;
- int fd1[2], fd2[2];
- /*
- * Set up sideband subprocess.
- *
- * We (parent) monitor and read from child, sending its fd#1 and fd#2
- * multiplexed out to our fd#1. If the child dies, we tell the other
- * end over channel #3.
- */
- if (pipe(fd1) < 0 || pipe(fd2) < 0) {
- int err = errno;
- packet_write(1, "NACK pipe failed on the remote side\n");
- die("upload-archive: %s", strerror(err));
- }
- writer = fork();
- if (writer < 0) {
+ const char *sent_argv[MAX_ARGS];
+ struct child_process cld = { sent_argv };
+ cld.out = cld.err = -1;
+ cld.git_cmd = 1;
+
+ if (argc != 2)
+ usage(upload_archive_usage);
+
+ if (!enter_repo(argv[1], 0))
+ die("'%s' does not appear to be a git repository", argv[1]);
+
+ prepare_argv(sent_argv, argv);
+ if (start_command(&cld)) {
int err = errno;
packet_write(1, "NACK fork failed on the remote side\n");
die("upload-archive: %s", strerror(err));
}
- if (!writer) {
- /* child - connect fd#1 and fd#2 to the pipe */
- dup2(fd1[1], 1);
- dup2(fd2[1], 2);
- close(fd1[1]); close(fd2[1]);
- close(fd1[0]); close(fd2[0]); /* we do not read from pipe */
-
- exit(run_upload_archive(argc, argv, prefix));
- }
/* parent - read from child, multiplex and send out to fd#1 */
- close(fd1[1]); close(fd2[1]); /* we do not write to pipe */
packet_write(1, "ACK\n");
packet_flush(1);
@@ -135,9 +109,9 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
struct pollfd pfd[2];
int status;
- pfd[0].fd = fd1[0];
+ pfd[0].fd = cld.out;
pfd[0].events = POLLIN;
- pfd[1].fd = fd2[0];
+ pfd[1].fd = cld.err;
pfd[1].events = POLLIN;
if (poll(pfd, 2, -1) < 0) {
if (errno != EINTR) {
@@ -156,7 +130,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
if (process_input(pfd[0].fd, 1))
continue;
- if (waitpid(writer, &status, 0) < 0)
+ if (waitpid(cld.pid, &status, 0) < 0)
error_clnt("%s", lostchild);
else if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
error_clnt("%s", deadchild);
diff --git a/compat/mingw.h b/compat/mingw.h
index fecf0d0..dfb0e87 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -85,8 +85,6 @@ static inline int symlink(const char *oldpath, const char *newpath)
{ errno = ENOSYS; return -1; }
static inline int fchmod(int fildes, mode_t mode)
{ errno = ENOSYS; return -1; }
-static inline pid_t fork(void)
-{ errno = ENOSYS; return -1; }
static inline unsigned int alarm(unsigned int seconds)
{ return 0; }
static inline int fsync(int fd)
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index d906898..889842e 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -96,7 +96,7 @@ test_expect_success 'git archive with --output' \
'git archive --output=b4.tar HEAD &&
test_cmp b.tar b4.tar'
-test_expect_success NOT_MINGW 'git archive --remote' \
+test_expect_success 'git archive --remote' \
'git archive --remote=. HEAD >b5.tar &&
test_cmp b.tar b5.tar'
@@ -266,7 +266,7 @@ test_expect_success 'archive --list mentions user filter' '
grep "^bar\$" output
'
-test_expect_success NOT_MINGW 'archive --list shows only enabled remote filters' '
+test_expect_success 'archive --list shows only enabled remote filters' '
git archive --list --remote=. >output &&
! grep "^tar\.foo\$" output &&
grep "^bar\$" output
@@ -298,7 +298,7 @@ test_expect_success 'extension matching requires dot' '
test_cmp b.tar config-implicittar.foo
'
-test_expect_success NOT_MINGW 'only enabled filters are available remotely' '
+test_expect_success 'only enabled filters are available remotely' '
test_must_fail git archive --remote=. --format=tar.foo HEAD \
>remote.tar.foo &&
git archive --remote=. --format=bar >remote.bar HEAD &&
@@ -341,12 +341,12 @@ test_expect_success GZIP,GUNZIP 'extract tgz file' '
test_cmp b.tar j.tar
'
-test_expect_success GZIP,NOT_MINGW 'remote tar.gz is allowed by default' '
+test_expect_success GZIP 'remote tar.gz is allowed by default' '
git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
test_cmp j.tgz remote.tar.gz
'
-test_expect_success GZIP,NOT_MINGW 'remote tar.gz can be disabled' '
+test_expect_success GZIP 'remote tar.gz can be disabled' '
git config tar.tar.gz.remote false &&
test_must_fail git archive --remote=. --format=tar.gz HEAD \
>remote.tar.gz
--
1.7.7.msysgit.1.1.g7b316
^ permalink raw reply related
* [PATCH v4 2/3] compat/win32/poll.c: upgrade from upstream
From: Erik Faye-Lund @ 2011-10-24 16:02 UTC (permalink / raw)
To: git; +Cc: gitster, j6t, peff, rene.scharfe
In-Reply-To: <1319472131-3968-1-git-send-email-kusmabite@gmail.com>
poll.c is updated from revision adc3a5b in
git://git.savannah.gnu.org/gnulib.git
The changes are applied with --whitespace=fix to reduce noise.
poll.h is not upgraded, because the most recent version now
contains template-stuff that breaks compilation for us.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
compat/win32/poll.c | 19 +++++++++++++------
1 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/compat/win32/poll.c b/compat/win32/poll.c
index 708a6c9..403eaa7 100644
--- a/compat/win32/poll.c
+++ b/compat/win32/poll.c
@@ -1,7 +1,7 @@
/* Emulation for poll(2)
Contributed by Paolo Bonzini.
- Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
+ Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
This file is part of gnulib.
@@ -27,7 +27,10 @@
#include <malloc.h>
#include <sys/types.h>
-#include "poll.h"
+
+/* Specification. */
+#include <poll.h>
+
#include <errno.h>
#include <limits.h>
#include <assert.h>
@@ -314,10 +317,7 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
#endif /* !MinGW */
int
-poll (pfd, nfd, timeout)
- struct pollfd *pfd;
- nfds_t nfd;
- int timeout;
+poll (struct pollfd *pfd, nfds_t nfd, int timeout)
{
#ifndef WIN32_NATIVE
fd_set rfds, wfds, efds;
@@ -454,6 +454,7 @@ poll (pfd, nfd, timeout)
if (!hEvent)
hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+restart:
handle_array[0] = hEvent;
nhandles = 1;
FD_ZERO (&rfds);
@@ -594,6 +595,12 @@ poll (pfd, nfd, timeout)
rc++;
}
+ if (!rc && timeout == INFTIM)
+ {
+ SwitchToThread();
+ goto restart;
+ }
+
return rc;
#endif
}
--
1.7.7.msysgit.1.1.g7b316
^ permalink raw reply related
* [PATCH v4 1/3] mingw: move poll out of sys-folder
From: Erik Faye-Lund @ 2011-10-24 16:02 UTC (permalink / raw)
To: git; +Cc: gitster, j6t, peff, rene.scharfe
In-Reply-To: <1319472131-3968-1-git-send-email-kusmabite@gmail.com>
Both XSI and upstream Gnulib versions expects to find poll.h at
the root of some include path, not inside the sys-folder.
This helps us when upgrading Gnulib.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
Makefile | 6 +-
compat/win32/poll.c | 599 +++++++++++++++++++++++++++++++++++++++++++++++
compat/win32/poll.h | 53 +++++
compat/win32/sys/poll.c | 599 -----------------------------------------------
compat/win32/sys/poll.h | 53 -----
5 files changed, 656 insertions(+), 654 deletions(-)
create mode 100644 compat/win32/poll.c
create mode 100644 compat/win32/poll.h
delete mode 100644 compat/win32/sys/poll.c
delete mode 100644 compat/win32/sys/poll.h
diff --git a/Makefile b/Makefile
index 3139c19..4c09b35 100644
--- a/Makefile
+++ b/Makefile
@@ -1088,6 +1088,7 @@ ifeq ($(uname_S),Windows)
NO_PREAD = YesPlease
NEEDS_CRYPTO_WITH_SSL = YesPlease
NO_LIBGEN_H = YesPlease
+ NO_SYS_POLL_H = YesPlease
NO_SYMLINK_HEAD = YesPlease
NO_IPV6 = YesPlease
NO_SETENV = YesPlease
@@ -1126,7 +1127,7 @@ ifeq ($(uname_S),Windows)
BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
COMPAT_OBJS = compat/msvc.o compat/winansi.o \
compat/win32/pthread.o compat/win32/syslog.o \
- compat/win32/sys/poll.o compat/win32/dirent.o
+ compat/win32/poll.o compat/win32/dirent.o
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
@@ -1181,6 +1182,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_PREAD = YesPlease
NEEDS_CRYPTO_WITH_SSL = YesPlease
NO_LIBGEN_H = YesPlease
+ NO_SYS_POLL_H = YesPlease
NO_SYMLINK_HEAD = YesPlease
NO_SETENV = YesPlease
NO_UNSETENV = YesPlease
@@ -1214,7 +1216,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
compat/win32/pthread.o compat/win32/syslog.o \
- compat/win32/sys/poll.o compat/win32/dirent.o
+ compat/win32/poll.o compat/win32/dirent.o
EXTLIBS += -lws2_32
PTHREAD_LIBS =
X = .exe
diff --git a/compat/win32/poll.c b/compat/win32/poll.c
new file mode 100644
index 0000000..708a6c9
--- /dev/null
+++ b/compat/win32/poll.c
@@ -0,0 +1,599 @@
+/* Emulation for poll(2)
+ Contributed by Paolo Bonzini.
+
+ Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
+
+ This file is part of gnulib.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Tell gcc not to warn about the (nfd < 0) tests, below. */
+#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#include <malloc.h>
+
+#include <sys/types.h>
+#include "poll.h"
+#include <errno.h>
+#include <limits.h>
+#include <assert.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_NATIVE
+# if defined (_MSC_VER)
+# define _WIN32_WINNT 0x0502
+# endif
+# include <winsock2.h>
+# include <windows.h>
+# include <io.h>
+# include <stdio.h>
+# include <conio.h>
+#else
+# include <sys/time.h>
+# include <sys/socket.h>
+# include <sys/select.h>
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#include <time.h>
+
+#ifndef INFTIM
+# define INFTIM (-1)
+#endif
+
+/* BeOS does not have MSG_PEEK. */
+#ifndef MSG_PEEK
+# define MSG_PEEK 0
+#endif
+
+#ifdef WIN32_NATIVE
+
+#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
+
+static BOOL
+IsSocketHandle (HANDLE h)
+{
+ WSANETWORKEVENTS ev;
+
+ if (IsConsoleHandle (h))
+ return FALSE;
+
+ /* Under Wine, it seems that getsockopt returns 0 for pipes too.
+ WSAEnumNetworkEvents instead distinguishes the two correctly. */
+ ev.lNetworkEvents = 0xDEADBEEF;
+ WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+ return ev.lNetworkEvents != 0xDEADBEEF;
+}
+
+/* Declare data structures for ntdll functions. */
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+ ULONG NamedPipeType;
+ ULONG NamedPipeConfiguration;
+ ULONG MaximumInstances;
+ ULONG CurrentInstances;
+ ULONG InboundQuota;
+ ULONG ReadDataAvailable;
+ ULONG OutboundQuota;
+ ULONG WriteQuotaAvailable;
+ ULONG NamedPipeState;
+ ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+ union {
+ DWORD Status;
+ PVOID Pointer;
+ } u;
+ ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef enum _FILE_INFORMATION_CLASS {
+ FilePipeLocalInformation = 24
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef DWORD (WINAPI *PNtQueryInformationFile)
+ (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
+
+# ifndef PIPE_BUF
+# define PIPE_BUF 512
+# endif
+
+/* Compute revents values for file handle H. If some events cannot happen
+ for the handle, eliminate them from *P_SOUGHT. */
+
+static int
+win32_compute_revents (HANDLE h, int *p_sought)
+{
+ int i, ret, happened;
+ INPUT_RECORD *irbuffer;
+ DWORD avail, nbuffer;
+ BOOL bRet;
+ IO_STATUS_BLOCK iosb;
+ FILE_PIPE_LOCAL_INFORMATION fpli;
+ static PNtQueryInformationFile NtQueryInformationFile;
+ static BOOL once_only;
+
+ switch (GetFileType (h))
+ {
+ case FILE_TYPE_PIPE:
+ if (!once_only)
+ {
+ NtQueryInformationFile = (PNtQueryInformationFile)
+ GetProcAddress (GetModuleHandle ("ntdll.dll"),
+ "NtQueryInformationFile");
+ once_only = TRUE;
+ }
+
+ happened = 0;
+ if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
+ {
+ if (avail)
+ happened |= *p_sought & (POLLIN | POLLRDNORM);
+ }
+ else if (GetLastError () == ERROR_BROKEN_PIPE)
+ happened |= POLLHUP;
+
+ else
+ {
+ /* It was the write-end of the pipe. Check if it is writable.
+ If NtQueryInformationFile fails, optimistically assume the pipe is
+ writable. This could happen on Win9x, where NtQueryInformationFile
+ is not available, or if we inherit a pipe that doesn't permit
+ FILE_READ_ATTRIBUTES access on the write end (I think this should
+ not happen since WinXP SP2; WINE seems fine too). Otherwise,
+ ensure that enough space is available for atomic writes. */
+ memset (&iosb, 0, sizeof (iosb));
+ memset (&fpli, 0, sizeof (fpli));
+
+ if (!NtQueryInformationFile
+ || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
+ FilePipeLocalInformation)
+ || fpli.WriteQuotaAvailable >= PIPE_BUF
+ || (fpli.OutboundQuota < PIPE_BUF &&
+ fpli.WriteQuotaAvailable == fpli.OutboundQuota))
+ happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
+ }
+ return happened;
+
+ case FILE_TYPE_CHAR:
+ ret = WaitForSingleObject (h, 0);
+ if (!IsConsoleHandle (h))
+ return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
+
+ nbuffer = avail = 0;
+ bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
+ if (bRet)
+ {
+ /* Input buffer. */
+ *p_sought &= POLLIN | POLLRDNORM;
+ if (nbuffer == 0)
+ return POLLHUP;
+ if (!*p_sought)
+ return 0;
+
+ irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
+ bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
+ if (!bRet || avail == 0)
+ return POLLHUP;
+
+ for (i = 0; i < avail; i++)
+ if (irbuffer[i].EventType == KEY_EVENT)
+ return *p_sought;
+ return 0;
+ }
+ else
+ {
+ /* Screen buffer. */
+ *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
+ return *p_sought;
+ }
+
+ default:
+ ret = WaitForSingleObject (h, 0);
+ if (ret == WAIT_OBJECT_0)
+ return *p_sought & ~(POLLPRI | POLLRDBAND);
+
+ return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
+ }
+}
+
+/* Convert fd_sets returned by select into revents values. */
+
+static int
+win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
+{
+ int happened = 0;
+
+ if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
+ happened |= (POLLIN | POLLRDNORM) & sought;
+
+ else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
+ {
+ int r, error;
+
+ char data[64];
+ WSASetLastError (0);
+ r = recv (h, data, sizeof (data), MSG_PEEK);
+ error = WSAGetLastError ();
+ WSASetLastError (0);
+
+ if (r > 0 || error == WSAENOTCONN)
+ happened |= (POLLIN | POLLRDNORM) & sought;
+
+ /* Distinguish hung-up sockets from other errors. */
+ else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
+ || error == WSAECONNABORTED || error == WSAENETRESET)
+ happened |= POLLHUP;
+
+ else
+ happened |= POLLERR;
+ }
+
+ if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
+ happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
+
+ if (lNetworkEvents & FD_OOB)
+ happened |= (POLLPRI | POLLRDBAND) & sought;
+
+ return happened;
+}
+
+#else /* !MinGW */
+
+/* Convert select(2) returned fd_sets into poll(2) revents values. */
+static int
+compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
+{
+ int happened = 0;
+ if (FD_ISSET (fd, rfds))
+ {
+ int r;
+ int socket_errno;
+
+# if defined __MACH__ && defined __APPLE__
+ /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
+ for some kinds of descriptors. Detect if this descriptor is a
+ connected socket, a server socket, or something else using a
+ 0-byte recv, and use ioctl(2) to detect POLLHUP. */
+ r = recv (fd, NULL, 0, MSG_PEEK);
+ socket_errno = (r < 0) ? errno : 0;
+ if (r == 0 || socket_errno == ENOTSOCK)
+ ioctl (fd, FIONREAD, &r);
+# else
+ char data[64];
+ r = recv (fd, data, sizeof (data), MSG_PEEK);
+ socket_errno = (r < 0) ? errno : 0;
+# endif
+ if (r == 0)
+ happened |= POLLHUP;
+
+ /* If the event happened on an unconnected server socket,
+ that's fine. */
+ else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
+ happened |= (POLLIN | POLLRDNORM) & sought;
+
+ /* Distinguish hung-up sockets from other errors. */
+ else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
+ || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
+ happened |= POLLHUP;
+
+ else
+ happened |= POLLERR;
+ }
+
+ if (FD_ISSET (fd, wfds))
+ happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
+
+ if (FD_ISSET (fd, efds))
+ happened |= (POLLPRI | POLLRDBAND) & sought;
+
+ return happened;
+}
+#endif /* !MinGW */
+
+int
+poll (pfd, nfd, timeout)
+ struct pollfd *pfd;
+ nfds_t nfd;
+ int timeout;
+{
+#ifndef WIN32_NATIVE
+ fd_set rfds, wfds, efds;
+ struct timeval tv;
+ struct timeval *ptv;
+ int maxfd, rc;
+ nfds_t i;
+
+# ifdef _SC_OPEN_MAX
+ static int sc_open_max = -1;
+
+ if (nfd < 0
+ || (nfd > sc_open_max
+ && (sc_open_max != -1
+ || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+# else /* !_SC_OPEN_MAX */
+# ifdef OPEN_MAX
+ if (nfd < 0 || nfd > OPEN_MAX)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+# endif /* OPEN_MAX -- else, no check is needed */
+# endif /* !_SC_OPEN_MAX */
+
+ /* EFAULT is not necessary to implement, but let's do it in the
+ simplest case. */
+ if (!pfd)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+
+ /* convert timeout number into a timeval structure */
+ if (timeout == 0)
+ {
+ ptv = &tv;
+ ptv->tv_sec = 0;
+ ptv->tv_usec = 0;
+ }
+ else if (timeout > 0)
+ {
+ ptv = &tv;
+ ptv->tv_sec = timeout / 1000;
+ ptv->tv_usec = (timeout % 1000) * 1000;
+ }
+ else if (timeout == INFTIM)
+ /* wait forever */
+ ptv = NULL;
+ else
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* create fd sets and determine max fd */
+ maxfd = -1;
+ FD_ZERO (&rfds);
+ FD_ZERO (&wfds);
+ FD_ZERO (&efds);
+ for (i = 0; i < nfd; i++)
+ {
+ if (pfd[i].fd < 0)
+ continue;
+
+ if (pfd[i].events & (POLLIN | POLLRDNORM))
+ FD_SET (pfd[i].fd, &rfds);
+
+ /* see select(2): "the only exceptional condition detectable
+ is out-of-band data received on a socket", hence we push
+ POLLWRBAND events onto wfds instead of efds. */
+ if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
+ FD_SET (pfd[i].fd, &wfds);
+ if (pfd[i].events & (POLLPRI | POLLRDBAND))
+ FD_SET (pfd[i].fd, &efds);
+ if (pfd[i].fd >= maxfd
+ && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
+ | POLLRDNORM | POLLRDBAND
+ | POLLWRNORM | POLLWRBAND)))
+ {
+ maxfd = pfd[i].fd;
+ if (maxfd > FD_SETSIZE)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ }
+ }
+
+ /* examine fd sets */
+ rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
+ if (rc < 0)
+ return rc;
+
+ /* establish results */
+ rc = 0;
+ for (i = 0; i < nfd; i++)
+ if (pfd[i].fd < 0)
+ pfd[i].revents = 0;
+ else
+ {
+ int happened = compute_revents (pfd[i].fd, pfd[i].events,
+ &rfds, &wfds, &efds);
+ if (happened)
+ {
+ pfd[i].revents = happened;
+ rc++;
+ }
+ }
+
+ return rc;
+#else
+ static struct timeval tv0;
+ static HANDLE hEvent;
+ WSANETWORKEVENTS ev;
+ HANDLE h, handle_array[FD_SETSIZE + 2];
+ DWORD ret, wait_timeout, nhandles;
+ fd_set rfds, wfds, xfds;
+ BOOL poll_again;
+ MSG msg;
+ int rc = 0;
+ nfds_t i;
+
+ if (nfd < 0 || timeout < -1)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!hEvent)
+ hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+ handle_array[0] = hEvent;
+ nhandles = 1;
+ FD_ZERO (&rfds);
+ FD_ZERO (&wfds);
+ FD_ZERO (&xfds);
+
+ /* Classify socket handles and create fd sets. */
+ for (i = 0; i < nfd; i++)
+ {
+ int sought = pfd[i].events;
+ pfd[i].revents = 0;
+ if (pfd[i].fd < 0)
+ continue;
+ if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
+ | POLLPRI | POLLRDBAND)))
+ continue;
+
+ h = (HANDLE) _get_osfhandle (pfd[i].fd);
+ assert (h != NULL);
+ if (IsSocketHandle (h))
+ {
+ int requested = FD_CLOSE;
+
+ /* see above; socket handles are mapped onto select. */
+ if (sought & (POLLIN | POLLRDNORM))
+ {
+ requested |= FD_READ | FD_ACCEPT;
+ FD_SET ((SOCKET) h, &rfds);
+ }
+ if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
+ {
+ requested |= FD_WRITE | FD_CONNECT;
+ FD_SET ((SOCKET) h, &wfds);
+ }
+ if (sought & (POLLPRI | POLLRDBAND))
+ {
+ requested |= FD_OOB;
+ FD_SET ((SOCKET) h, &xfds);
+ }
+
+ if (requested)
+ WSAEventSelect ((SOCKET) h, hEvent, requested);
+ }
+ else
+ {
+ /* Poll now. If we get an event, do not poll again. Also,
+ screen buffer handles are waitable, and they'll block until
+ a character is available. win32_compute_revents eliminates
+ bits for the "wrong" direction. */
+ pfd[i].revents = win32_compute_revents (h, &sought);
+ if (sought)
+ handle_array[nhandles++] = h;
+ if (pfd[i].revents)
+ timeout = 0;
+ }
+ }
+
+ if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
+ {
+ /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
+ no need to call select again. */
+ poll_again = FALSE;
+ wait_timeout = 0;
+ }
+ else
+ {
+ poll_again = TRUE;
+ if (timeout == INFTIM)
+ wait_timeout = INFINITE;
+ else
+ wait_timeout = timeout;
+ }
+
+ for (;;)
+ {
+ ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
+ wait_timeout, QS_ALLINPUT);
+
+ if (ret == WAIT_OBJECT_0 + nhandles)
+ {
+ /* new input of some other kind */
+ BOOL bRet;
+ while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ else
+ break;
+ }
+
+ if (poll_again)
+ select (0, &rfds, &wfds, &xfds, &tv0);
+
+ /* Place a sentinel at the end of the array. */
+ handle_array[nhandles] = NULL;
+ nhandles = 1;
+ for (i = 0; i < nfd; i++)
+ {
+ int happened;
+
+ if (pfd[i].fd < 0)
+ continue;
+ if (!(pfd[i].events & (POLLIN | POLLRDNORM |
+ POLLOUT | POLLWRNORM | POLLWRBAND)))
+ continue;
+
+ h = (HANDLE) _get_osfhandle (pfd[i].fd);
+ if (h != handle_array[nhandles])
+ {
+ /* It's a socket. */
+ WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+ WSAEventSelect ((SOCKET) h, 0, 0);
+
+ /* If we're lucky, WSAEnumNetworkEvents already provided a way
+ to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
+ if (FD_ISSET ((SOCKET) h, &rfds)
+ && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
+ ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
+ if (FD_ISSET ((SOCKET) h, &wfds))
+ ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
+ if (FD_ISSET ((SOCKET) h, &xfds))
+ ev.lNetworkEvents |= FD_OOB;
+
+ happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
+ ev.lNetworkEvents);
+ }
+ else
+ {
+ /* Not a socket. */
+ int sought = pfd[i].events;
+ happened = win32_compute_revents (h, &sought);
+ nhandles++;
+ }
+
+ if ((pfd[i].revents |= happened) != 0)
+ rc++;
+ }
+
+ return rc;
+#endif
+}
diff --git a/compat/win32/poll.h b/compat/win32/poll.h
new file mode 100644
index 0000000..b7aa59d
--- /dev/null
+++ b/compat/win32/poll.h
@@ -0,0 +1,53 @@
+/* Header for poll(2) emulation
+ Contributed by Paolo Bonzini.
+
+ Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
+
+ This file is part of gnulib.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _GL_POLL_H
+#define _GL_POLL_H
+
+/* fake a poll(2) environment */
+#define POLLIN 0x0001 /* any readable data available */
+#define POLLPRI 0x0002 /* OOB/Urgent readable data */
+#define POLLOUT 0x0004 /* file descriptor is writeable */
+#define POLLERR 0x0008 /* some poll error occurred */
+#define POLLHUP 0x0010 /* file descriptor was "hung up" */
+#define POLLNVAL 0x0020 /* requested events "invalid" */
+#define POLLRDNORM 0x0040
+#define POLLRDBAND 0x0080
+#define POLLWRNORM 0x0100
+#define POLLWRBAND 0x0200
+
+struct pollfd
+{
+ int fd; /* which file descriptor to poll */
+ short events; /* events we are interested in */
+ short revents; /* events found on return */
+};
+
+typedef unsigned long nfds_t;
+
+extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
+
+/* Define INFTIM only if doing so conforms to POSIX. */
+#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
+#define INFTIM (-1)
+#endif
+
+#endif /* _GL_POLL_H */
diff --git a/compat/win32/sys/poll.c b/compat/win32/sys/poll.c
deleted file mode 100644
index 708a6c9..0000000
--- a/compat/win32/sys/poll.c
+++ /dev/null
@@ -1,599 +0,0 @@
-/* Emulation for poll(2)
- Contributed by Paolo Bonzini.
-
- Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
-
- This file is part of gnulib.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-
-/* Tell gcc not to warn about the (nfd < 0) tests, below. */
-#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
-# pragma GCC diagnostic ignored "-Wtype-limits"
-#endif
-
-#include <malloc.h>
-
-#include <sys/types.h>
-#include "poll.h"
-#include <errno.h>
-#include <limits.h>
-#include <assert.h>
-
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-# define WIN32_NATIVE
-# if defined (_MSC_VER)
-# define _WIN32_WINNT 0x0502
-# endif
-# include <winsock2.h>
-# include <windows.h>
-# include <io.h>
-# include <stdio.h>
-# include <conio.h>
-#else
-# include <sys/time.h>
-# include <sys/socket.h>
-# include <sys/select.h>
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-
-#include <time.h>
-
-#ifndef INFTIM
-# define INFTIM (-1)
-#endif
-
-/* BeOS does not have MSG_PEEK. */
-#ifndef MSG_PEEK
-# define MSG_PEEK 0
-#endif
-
-#ifdef WIN32_NATIVE
-
-#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
-
-static BOOL
-IsSocketHandle (HANDLE h)
-{
- WSANETWORKEVENTS ev;
-
- if (IsConsoleHandle (h))
- return FALSE;
-
- /* Under Wine, it seems that getsockopt returns 0 for pipes too.
- WSAEnumNetworkEvents instead distinguishes the two correctly. */
- ev.lNetworkEvents = 0xDEADBEEF;
- WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
- return ev.lNetworkEvents != 0xDEADBEEF;
-}
-
-/* Declare data structures for ntdll functions. */
-typedef struct _FILE_PIPE_LOCAL_INFORMATION {
- ULONG NamedPipeType;
- ULONG NamedPipeConfiguration;
- ULONG MaximumInstances;
- ULONG CurrentInstances;
- ULONG InboundQuota;
- ULONG ReadDataAvailable;
- ULONG OutboundQuota;
- ULONG WriteQuotaAvailable;
- ULONG NamedPipeState;
- ULONG NamedPipeEnd;
-} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
-
-typedef struct _IO_STATUS_BLOCK
-{
- union {
- DWORD Status;
- PVOID Pointer;
- } u;
- ULONG_PTR Information;
-} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
-
-typedef enum _FILE_INFORMATION_CLASS {
- FilePipeLocalInformation = 24
-} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
-
-typedef DWORD (WINAPI *PNtQueryInformationFile)
- (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
-
-# ifndef PIPE_BUF
-# define PIPE_BUF 512
-# endif
-
-/* Compute revents values for file handle H. If some events cannot happen
- for the handle, eliminate them from *P_SOUGHT. */
-
-static int
-win32_compute_revents (HANDLE h, int *p_sought)
-{
- int i, ret, happened;
- INPUT_RECORD *irbuffer;
- DWORD avail, nbuffer;
- BOOL bRet;
- IO_STATUS_BLOCK iosb;
- FILE_PIPE_LOCAL_INFORMATION fpli;
- static PNtQueryInformationFile NtQueryInformationFile;
- static BOOL once_only;
-
- switch (GetFileType (h))
- {
- case FILE_TYPE_PIPE:
- if (!once_only)
- {
- NtQueryInformationFile = (PNtQueryInformationFile)
- GetProcAddress (GetModuleHandle ("ntdll.dll"),
- "NtQueryInformationFile");
- once_only = TRUE;
- }
-
- happened = 0;
- if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
- {
- if (avail)
- happened |= *p_sought & (POLLIN | POLLRDNORM);
- }
- else if (GetLastError () == ERROR_BROKEN_PIPE)
- happened |= POLLHUP;
-
- else
- {
- /* It was the write-end of the pipe. Check if it is writable.
- If NtQueryInformationFile fails, optimistically assume the pipe is
- writable. This could happen on Win9x, where NtQueryInformationFile
- is not available, or if we inherit a pipe that doesn't permit
- FILE_READ_ATTRIBUTES access on the write end (I think this should
- not happen since WinXP SP2; WINE seems fine too). Otherwise,
- ensure that enough space is available for atomic writes. */
- memset (&iosb, 0, sizeof (iosb));
- memset (&fpli, 0, sizeof (fpli));
-
- if (!NtQueryInformationFile
- || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
- FilePipeLocalInformation)
- || fpli.WriteQuotaAvailable >= PIPE_BUF
- || (fpli.OutboundQuota < PIPE_BUF &&
- fpli.WriteQuotaAvailable == fpli.OutboundQuota))
- happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
- }
- return happened;
-
- case FILE_TYPE_CHAR:
- ret = WaitForSingleObject (h, 0);
- if (!IsConsoleHandle (h))
- return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
-
- nbuffer = avail = 0;
- bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
- if (bRet)
- {
- /* Input buffer. */
- *p_sought &= POLLIN | POLLRDNORM;
- if (nbuffer == 0)
- return POLLHUP;
- if (!*p_sought)
- return 0;
-
- irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
- bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
- if (!bRet || avail == 0)
- return POLLHUP;
-
- for (i = 0; i < avail; i++)
- if (irbuffer[i].EventType == KEY_EVENT)
- return *p_sought;
- return 0;
- }
- else
- {
- /* Screen buffer. */
- *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
- return *p_sought;
- }
-
- default:
- ret = WaitForSingleObject (h, 0);
- if (ret == WAIT_OBJECT_0)
- return *p_sought & ~(POLLPRI | POLLRDBAND);
-
- return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
- }
-}
-
-/* Convert fd_sets returned by select into revents values. */
-
-static int
-win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
-{
- int happened = 0;
-
- if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
- happened |= (POLLIN | POLLRDNORM) & sought;
-
- else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
- {
- int r, error;
-
- char data[64];
- WSASetLastError (0);
- r = recv (h, data, sizeof (data), MSG_PEEK);
- error = WSAGetLastError ();
- WSASetLastError (0);
-
- if (r > 0 || error == WSAENOTCONN)
- happened |= (POLLIN | POLLRDNORM) & sought;
-
- /* Distinguish hung-up sockets from other errors. */
- else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
- || error == WSAECONNABORTED || error == WSAENETRESET)
- happened |= POLLHUP;
-
- else
- happened |= POLLERR;
- }
-
- if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
- happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
-
- if (lNetworkEvents & FD_OOB)
- happened |= (POLLPRI | POLLRDBAND) & sought;
-
- return happened;
-}
-
-#else /* !MinGW */
-
-/* Convert select(2) returned fd_sets into poll(2) revents values. */
-static int
-compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
-{
- int happened = 0;
- if (FD_ISSET (fd, rfds))
- {
- int r;
- int socket_errno;
-
-# if defined __MACH__ && defined __APPLE__
- /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
- for some kinds of descriptors. Detect if this descriptor is a
- connected socket, a server socket, or something else using a
- 0-byte recv, and use ioctl(2) to detect POLLHUP. */
- r = recv (fd, NULL, 0, MSG_PEEK);
- socket_errno = (r < 0) ? errno : 0;
- if (r == 0 || socket_errno == ENOTSOCK)
- ioctl (fd, FIONREAD, &r);
-# else
- char data[64];
- r = recv (fd, data, sizeof (data), MSG_PEEK);
- socket_errno = (r < 0) ? errno : 0;
-# endif
- if (r == 0)
- happened |= POLLHUP;
-
- /* If the event happened on an unconnected server socket,
- that's fine. */
- else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
- happened |= (POLLIN | POLLRDNORM) & sought;
-
- /* Distinguish hung-up sockets from other errors. */
- else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
- || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
- happened |= POLLHUP;
-
- else
- happened |= POLLERR;
- }
-
- if (FD_ISSET (fd, wfds))
- happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
-
- if (FD_ISSET (fd, efds))
- happened |= (POLLPRI | POLLRDBAND) & sought;
-
- return happened;
-}
-#endif /* !MinGW */
-
-int
-poll (pfd, nfd, timeout)
- struct pollfd *pfd;
- nfds_t nfd;
- int timeout;
-{
-#ifndef WIN32_NATIVE
- fd_set rfds, wfds, efds;
- struct timeval tv;
- struct timeval *ptv;
- int maxfd, rc;
- nfds_t i;
-
-# ifdef _SC_OPEN_MAX
- static int sc_open_max = -1;
-
- if (nfd < 0
- || (nfd > sc_open_max
- && (sc_open_max != -1
- || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
- {
- errno = EINVAL;
- return -1;
- }
-# else /* !_SC_OPEN_MAX */
-# ifdef OPEN_MAX
- if (nfd < 0 || nfd > OPEN_MAX)
- {
- errno = EINVAL;
- return -1;
- }
-# endif /* OPEN_MAX -- else, no check is needed */
-# endif /* !_SC_OPEN_MAX */
-
- /* EFAULT is not necessary to implement, but let's do it in the
- simplest case. */
- if (!pfd)
- {
- errno = EFAULT;
- return -1;
- }
-
- /* convert timeout number into a timeval structure */
- if (timeout == 0)
- {
- ptv = &tv;
- ptv->tv_sec = 0;
- ptv->tv_usec = 0;
- }
- else if (timeout > 0)
- {
- ptv = &tv;
- ptv->tv_sec = timeout / 1000;
- ptv->tv_usec = (timeout % 1000) * 1000;
- }
- else if (timeout == INFTIM)
- /* wait forever */
- ptv = NULL;
- else
- {
- errno = EINVAL;
- return -1;
- }
-
- /* create fd sets and determine max fd */
- maxfd = -1;
- FD_ZERO (&rfds);
- FD_ZERO (&wfds);
- FD_ZERO (&efds);
- for (i = 0; i < nfd; i++)
- {
- if (pfd[i].fd < 0)
- continue;
-
- if (pfd[i].events & (POLLIN | POLLRDNORM))
- FD_SET (pfd[i].fd, &rfds);
-
- /* see select(2): "the only exceptional condition detectable
- is out-of-band data received on a socket", hence we push
- POLLWRBAND events onto wfds instead of efds. */
- if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
- FD_SET (pfd[i].fd, &wfds);
- if (pfd[i].events & (POLLPRI | POLLRDBAND))
- FD_SET (pfd[i].fd, &efds);
- if (pfd[i].fd >= maxfd
- && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
- | POLLRDNORM | POLLRDBAND
- | POLLWRNORM | POLLWRBAND)))
- {
- maxfd = pfd[i].fd;
- if (maxfd > FD_SETSIZE)
- {
- errno = EOVERFLOW;
- return -1;
- }
- }
- }
-
- /* examine fd sets */
- rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
- if (rc < 0)
- return rc;
-
- /* establish results */
- rc = 0;
- for (i = 0; i < nfd; i++)
- if (pfd[i].fd < 0)
- pfd[i].revents = 0;
- else
- {
- int happened = compute_revents (pfd[i].fd, pfd[i].events,
- &rfds, &wfds, &efds);
- if (happened)
- {
- pfd[i].revents = happened;
- rc++;
- }
- }
-
- return rc;
-#else
- static struct timeval tv0;
- static HANDLE hEvent;
- WSANETWORKEVENTS ev;
- HANDLE h, handle_array[FD_SETSIZE + 2];
- DWORD ret, wait_timeout, nhandles;
- fd_set rfds, wfds, xfds;
- BOOL poll_again;
- MSG msg;
- int rc = 0;
- nfds_t i;
-
- if (nfd < 0 || timeout < -1)
- {
- errno = EINVAL;
- return -1;
- }
-
- if (!hEvent)
- hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
-
- handle_array[0] = hEvent;
- nhandles = 1;
- FD_ZERO (&rfds);
- FD_ZERO (&wfds);
- FD_ZERO (&xfds);
-
- /* Classify socket handles and create fd sets. */
- for (i = 0; i < nfd; i++)
- {
- int sought = pfd[i].events;
- pfd[i].revents = 0;
- if (pfd[i].fd < 0)
- continue;
- if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
- | POLLPRI | POLLRDBAND)))
- continue;
-
- h = (HANDLE) _get_osfhandle (pfd[i].fd);
- assert (h != NULL);
- if (IsSocketHandle (h))
- {
- int requested = FD_CLOSE;
-
- /* see above; socket handles are mapped onto select. */
- if (sought & (POLLIN | POLLRDNORM))
- {
- requested |= FD_READ | FD_ACCEPT;
- FD_SET ((SOCKET) h, &rfds);
- }
- if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
- {
- requested |= FD_WRITE | FD_CONNECT;
- FD_SET ((SOCKET) h, &wfds);
- }
- if (sought & (POLLPRI | POLLRDBAND))
- {
- requested |= FD_OOB;
- FD_SET ((SOCKET) h, &xfds);
- }
-
- if (requested)
- WSAEventSelect ((SOCKET) h, hEvent, requested);
- }
- else
- {
- /* Poll now. If we get an event, do not poll again. Also,
- screen buffer handles are waitable, and they'll block until
- a character is available. win32_compute_revents eliminates
- bits for the "wrong" direction. */
- pfd[i].revents = win32_compute_revents (h, &sought);
- if (sought)
- handle_array[nhandles++] = h;
- if (pfd[i].revents)
- timeout = 0;
- }
- }
-
- if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
- {
- /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
- no need to call select again. */
- poll_again = FALSE;
- wait_timeout = 0;
- }
- else
- {
- poll_again = TRUE;
- if (timeout == INFTIM)
- wait_timeout = INFINITE;
- else
- wait_timeout = timeout;
- }
-
- for (;;)
- {
- ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
- wait_timeout, QS_ALLINPUT);
-
- if (ret == WAIT_OBJECT_0 + nhandles)
- {
- /* new input of some other kind */
- BOOL bRet;
- while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
- {
- TranslateMessage (&msg);
- DispatchMessage (&msg);
- }
- }
- else
- break;
- }
-
- if (poll_again)
- select (0, &rfds, &wfds, &xfds, &tv0);
-
- /* Place a sentinel at the end of the array. */
- handle_array[nhandles] = NULL;
- nhandles = 1;
- for (i = 0; i < nfd; i++)
- {
- int happened;
-
- if (pfd[i].fd < 0)
- continue;
- if (!(pfd[i].events & (POLLIN | POLLRDNORM |
- POLLOUT | POLLWRNORM | POLLWRBAND)))
- continue;
-
- h = (HANDLE) _get_osfhandle (pfd[i].fd);
- if (h != handle_array[nhandles])
- {
- /* It's a socket. */
- WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
- WSAEventSelect ((SOCKET) h, 0, 0);
-
- /* If we're lucky, WSAEnumNetworkEvents already provided a way
- to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
- if (FD_ISSET ((SOCKET) h, &rfds)
- && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
- ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
- if (FD_ISSET ((SOCKET) h, &wfds))
- ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
- if (FD_ISSET ((SOCKET) h, &xfds))
- ev.lNetworkEvents |= FD_OOB;
-
- happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
- ev.lNetworkEvents);
- }
- else
- {
- /* Not a socket. */
- int sought = pfd[i].events;
- happened = win32_compute_revents (h, &sought);
- nhandles++;
- }
-
- if ((pfd[i].revents |= happened) != 0)
- rc++;
- }
-
- return rc;
-#endif
-}
diff --git a/compat/win32/sys/poll.h b/compat/win32/sys/poll.h
deleted file mode 100644
index b7aa59d..0000000
--- a/compat/win32/sys/poll.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Header for poll(2) emulation
- Contributed by Paolo Bonzini.
-
- Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
-
- This file is part of gnulib.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-
-#ifndef _GL_POLL_H
-#define _GL_POLL_H
-
-/* fake a poll(2) environment */
-#define POLLIN 0x0001 /* any readable data available */
-#define POLLPRI 0x0002 /* OOB/Urgent readable data */
-#define POLLOUT 0x0004 /* file descriptor is writeable */
-#define POLLERR 0x0008 /* some poll error occurred */
-#define POLLHUP 0x0010 /* file descriptor was "hung up" */
-#define POLLNVAL 0x0020 /* requested events "invalid" */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-
-struct pollfd
-{
- int fd; /* which file descriptor to poll */
- short events; /* events we are interested in */
- short revents; /* events found on return */
-};
-
-typedef unsigned long nfds_t;
-
-extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
-
-/* Define INFTIM only if doing so conforms to POSIX. */
-#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
-#define INFTIM (-1)
-#endif
-
-#endif /* _GL_POLL_H */
--
1.7.7.msysgit.1.1.g7b316
^ permalink raw reply related
* [PATCH v4 0/3] port upload-archive to Windows
From: Erik Faye-Lund @ 2011-10-24 16:02 UTC (permalink / raw)
To: git; +Cc: gitster, j6t, peff, rene.scharfe
Here's a new iteration of this series. I delayed it until the
improved version of "enter_repo: do not modify input" hit master,
which happened recently.
The important change in this iteration (besides the patch that
already propagated upstream) is that I've moved
compat/win32/sys/poll.[ch] out of the sys-folder (as XSI suggests).
This enables us to easily upgrade the poll-emulation without
breaking the Windows build in the process.
Erik Faye-Lund (3):
mingw: move poll out of sys-folder
compat/win32/poll.c: upgrade from upstream
upload-archive: use start_command instead of fork
Makefile | 6 +-
builtin/archive.c | 6 +-
builtin/upload-archive.c | 68 ++----
compat/mingw.h | 2 -
compat/win32/poll.c | 606 ++++++++++++++++++++++++++++++++++++++++++++++
compat/win32/poll.h | 53 ++++
compat/win32/sys/poll.c | 599 ---------------------------------------------
compat/win32/sys/poll.h | 53 ----
t/t5000-tar-tree.sh | 10 +-
9 files changed, 694 insertions(+), 709 deletions(-)
create mode 100644 compat/win32/poll.c
create mode 100644 compat/win32/poll.h
delete mode 100644 compat/win32/sys/poll.c
delete mode 100644 compat/win32/sys/poll.h
--
1.7.7.msysgit.1.1.g7b316
^ permalink raw reply
* Re: [PATCH] read-cache.c: fix index memory allocation
From: René Scharfe @ 2011-10-24 15:59 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, John Hsing, Matthieu Moy, git
In-Reply-To: <7vipne50lz.fsf@alter.siamese.dyndns.org>
Am 24.10.2011 09:07, schrieb Junio C Hamano:
> Thanks.
>
> This approach may be the most appropriate for the maintenance track, but
> for the purpose of going forward, I wonder if we really want to keep the
> "estimate and allocate a large pool, and carve out individual pieces".
>
> This bulk-allocate dates back to the days when we didn't have ondisk vs
> incore representation differences, IIRC, and as the result we deliberately
> leak cache entries whenever an entry in the index is replaced with a new
> one. Does the overhead to allocate individually really kill us that much
> for say a tree with 30k files in it?
Probably not; unpack_trees() does that already. (It calls
create_ce_entry() via unpack_nondirectories() via unpack_callback() via
traverse_trees()).
René
^ permalink raw reply
* Re: [PATCH] read-cache.c: fix index memory allocation
From: René Scharfe @ 2011-10-24 15:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, John Hsing, Matthieu Moy, git
In-Reply-To: <7vaa8q4zm9.fsf@alter.siamese.dyndns.org>
Am 24.10.2011 09:28, schrieb Junio C Hamano:
> René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
>
>> t/t7510-status-index.sh | 50 +++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 53 insertions(+), 3 deletions(-)
>> create mode 100755 t/t7510-status-index.sh
>
>> diff --git a/t/t7510-status-index.sh b/t/t7510-status-index.sh
>> new file mode 100755
>> index 0000000..bca359d
>> --- /dev/null
>> +++ b/t/t7510-status-index.sh
>> @@ -0,0 +1,50 @@
>
> Hmm, I cannot seem to make this fail this test without the fix on my
> Fedora 14 i686 VM when applied to v1.7.6.4 (estimation code originates
> cf55870 back in v1.7.6.1 days), but it does break on 'master'.
Err, yes, I forgot to mention in the commit message that on my test
system the breakage occurs only after 2548183ba, "fix phantom untracked
files when core.ignorecase is set", which adds the pointer dir_next to
struct cache_entry. This seems to have caused an unlucky constellation
of offsets and struct sizes for the size estimator.
> By the way, I'll move this to 7511.
>
> Also would a patch like this help?
Only a little, I suspect. If we've moved past the end then it's too
late. And if we catch the error before it happens, dying is only
slightly better than crashing.
> -- >8 --
> Subject: [PATCH] read_index(): die on estimation error
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
> read-cache.c | 7 ++++++-
> 1 files changed, 6 insertions(+), 1 deletions(-)
>
> diff --git a/read-cache.c b/read-cache.c
> index 0a64103..2926615 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -1270,6 +1270,7 @@ int read_index_from(struct index_state *istate, const char *path)
> int fd, i;
> struct stat st;
> unsigned long src_offset, dst_offset;
> + size_t bulk_alloc_size;
> struct cache_header *hdr;
> void *mmap;
> size_t mmap_size;
> @@ -1315,7 +1316,8 @@ int read_index_from(struct index_state *istate, const char *path)
> * has room for a few more flags, we can allocate using the same
> * index size
> */
> - istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
> + bulk_alloc_size = estimate_cache_size(mmap_size, istate->cache_nr);
> + istate->alloc = xmalloc(bulk_alloc_size);
> istate->initialized = 1;
>
> src_offset = sizeof(*hdr);
> @@ -1331,7 +1333,9 @@ int read_index_from(struct index_state *istate, const char *path)
>
> src_offset += ondisk_ce_size(ce);
> dst_offset += ce_size(ce);
> + if (bulk_alloc_size <= dst_offset)
> + die("cache size estimation error");
> }
> istate->timestamp.sec = st.st_mtime;
> istate->timestamp.nsec = ST_MTIME_NSEC(st);
>
^ permalink raw reply
* A note from the maintainer
From: Junio C Hamano @ 2011-10-24 15:32 UTC (permalink / raw)
To: git
Welcome to git development community.
This message is written by the maintainer and talks about how Git
project is managed, and how you can work with it.
* Mailing list and the community
The development is primarily done on the Git mailing list. Help
requests, feature proposals, bug reports and patches should be sent to
the list address <git@vger.kernel.org>. You don't have to be
subscribed to send messages. The convention on the list is to keep
everybody involved on Cc:, so it is unnecessary to ask "Please Cc: me,
I am not subscribed".
Before sending patches, please read Documentation/SubmittingPatches
and Documentation/CodingGuidelines to familiarize yourself with the
project convention.
If you sent a patch and you did not hear any response from anybody for
several days, it could be that your patch was totally uninteresting,
but it also is possible that it was simply lost in the noise. Please
do not hesitate to send a reminder message in such a case. Messages
getting lost in the noise is a sign that people involved don't have
enough mental/time bandwidth to process them right at the moment, and
it often helps to wait until the list traffic becomes calmer before
sending such a reminder.
The list archive is available at a few public sites as well:
http://news.gmane.org/gmane.comp.version-control.git/
http://marc.theaimsgroup.com/?l=git
http://www.spinics.net/lists/git/
and some people seem to prefer to read it over NNTP:
nntp://news.gmane.org/gmane.comp.version-control.git
When you point at a message in a mailing list archive, using
gmane is often the easiest to follow by readers, like this:
http://thread.gmane.org/gmane.comp.version-control.git/27/focus=217
as it also allows people who subscribe to the mailing list as gmane
newsgroup to "jump to" the article.
Some members of the development community can sometimes also be found
on the #git IRC channel on Freenode. Its log is available at:
http://colabti.org/irclogger/irclogger_log/git
* Reporting bugs
When you think git does not behave as you expect, please do not stop your
bug report with just "git does not work". "I tried to do X but it did not
work" is not much better, neither is "I tried to do X and git did Y, which
is broken". It often is that what you expect is _not_ what other people
expect, and chances are that what you expect is very different from what
people who have worked on git have expected (otherwise, the behavior
would have been changed to match that expectation long time ago).
Please remember to always state
- what you wanted to do;
- what you did (the version of git and the command sequence to reproduce
the behavior);
- what you saw happen;
- what you expected to see; and
- how the last two are different.
See http://www.chiark.greenend.org.uk/~sgtatham/bugs.html for further
hints.
* Repositories, branches and documentation.
My public git.git repository is at:
git://git.kernel.org/pub/scm/git/git.git/
git://repo.or.cz/alt-git.git
https://github.com/git/git
https://code.google.com/p/git-core/
Impatient people might have better luck with the latter two (there are a
few other mirrors I push into at sourceforge and github as well).
Their gitweb interfaces are found at:
http://git.kernel.org/?p=git/git.git
http://repo.or.cz/w/alt-git.git
There are three branches in git.git repository that are not about the
source tree of git: "html", "man", and "todo".
The "html" and "man" are preformatted documentation from the tip of
the "master" branch; the tip of "html" is visible at:
http://www.kernel.org/pub/software/scm/git/docs/
http://git-core.googlecode.com/git-history/html/git.html
The above URL is the top-level documentation page, and it may have
links to documentation of older releases.
The "todo" branch was originally meant to contain a TODO list for me,
but is mostly used to keep some helper scripts I use to maintain git.
For example, the script that was used to maintain the two documentation
branches are found there as dodoc.sh, which may be a good demonstration
of how to use a post-update hook to automate a task after pushing into a
repository.
There are four branches in git.git repository that track the source tree
of git: "master", "maint", "next", and "pu".
The "master" branch is meant to contain what are very well tested and
ready to be used in a production setting. Every now and then, a "feature
release" is cut from the tip of this branch and they typically are named
with three dotted decimal digits. The last such release was 1.7.7 done on
Sept 30, 2011. You can expect that the tip of the "master" branch is always
more stable than any of the released versions.
Whenever a feature release is made, "maint" branch is forked off from
"master" at that point. Obvious, safe and urgent fixes after a feature
release are applied to this branch and maintenance releases are cut from
it. The maintenance releases are named with four dotted decimal, named
after the feature release they are updates to; the last such release was
1.7.7.1. New features never go to this branch. This branch is also
merged into "master" to propagate the fixes forward.
A new development does not usually happen on "master". When you send a
series of patches, after review on the mailing list, a separate topic
branch is forked from the tip of "master" and your patches are queued
there, and kept out of "master" while people test it out. The quality of
topic branches are judged primarily by the mailing list discussions.
Topic branches that are in good shape are merged to the "next" branch. In
general, the "next" branch always contains the tip of "master". It might
not be quite rock-solid production ready, but is expected to work more or
less without major breakage. The "next" branch is where new and exciting
things take place. A topic that is in "next" is expected to be polished to
perfection before it is merged to "master" (that's why "master" can be
expected to stay more stable than any released version).
The "pu" (proposed updates) branch bundles all the remaining topic
branches. The topics on the branch are not complete, well tested, nor well
documented and need further work. When a topic that was in "pu" proves to
be in testable shape, it is merged to "next".
You can run "git log --first-parent master..pu" to see what topics are
currently in flight. Sometimes, an idea that looked promising turns out
to be not so good and the topic can be dropped from "pu" in such a case.
The two branches "master" and "maint" are never rewound, and "next"
usually will not be either. After a feature release is made from
"master", however, "next" will be rebuilt from the tip of "master"
using the topics that didn't make the cut in the feature release.
Note that being in "next" is not a guarantee to appear in the next
release, nor even in any future release. There were cases that topics
needed reverting a few commits in them before graduating to "master",
or a topic that already was in "next" was reverted from "next" because
fatal flaws were found in it after it was merged.
* Other people's trees, trusted lieutenants and credits.
Documentation/SubmittingPatches outlines to whom your proposed changes
should be sent. As described in contrib/README, I would delegate fixes
and enhancements in contrib/ area to the primary contributors of them.
Although the following are included in git.git repository, they have their
own authoritative repository and maintainers:
- git-gui/ comes from git-gui project, maintained by Pat Thoyts:
git://repo.or.cz/git-gui.git
- gitk-git/ comes from Paul Mackerras's gitk project:
git://git.kernel.org/pub/scm/gitk/gitk.git
I would like to thank everybody who helped to raise git into the current
shape. Especially I would like to thank the git list regulars whose help
I have relied on and expect to continue relying on heavily:
- Linus Torvalds, Shawn Pearce, Johannes Schindelin, Nicolas Pitre,
René Scharfe, Jeff King, Jonathan Nieder, Johan Herland, Johannes
Sixt, Sverre Rabbelier, Michael J Gruber, Nguyễn Thái Ngọc Duy,
Ævar Arnfjörð Bjarmason and Thomas Rast on general design and
implementation issues and reviews on the mailing list.
- Shawn and Nicolas Pitre on pack issues.
- Martin Langhoff, Frank Lichtenheld and Ævar Arnfjörð Bjarmason on
cvsserver and cvsimport.
- Paul Mackerras on gitk.
- Eric Wong, David D. Kilzer and Sam Vilain on git-svn.
- Simon Hausmann and Pete Wyckoff on git-p4.
- Jakub Narebski, John Hawley, Petr Baudis, Luben Tuikov, Giuseppe Bilotta on
gitweb.
- J. Bruce Fields, Jonathan Nieder, Michael J Gruber and Thomas Rast on
documentation (and countless others for proofreading and fixing).
- Alexandre Julliard on Emacs integration.
- David Aguilar and Charles Bailey for taking good care of git-mergetool
(and Theodore Ts'o for creating it in the first place) and git-difftool.
- Johannes Schindelin, Johannes Sixt, Erik Faye-Lund, Pat Thoyts and others
for their effort to move things forward on the Windows front.
- People on non-Linux platforms for keeping their eyes on portability;
especially, Randal Schwartz, Theodore Ts'o, Jason Riedy, Thomas Glanzmann,
Brandon Casey, Jeff King, Alex Riesen and countless others.
* This document
The latest copy of this document is found in git.git repository,
on 'todo' branch, as MaintNotes.
^ permalink raw reply
* What's cooking in git.git (Oct 2011, #09; Sun, 23)
From: Junio C Hamano @ 2011-10-24 15:31 UTC (permalink / raw)
To: git
Here are the topics that have been cooking. Commits prefixed with '-' are
only in 'pu' (proposed updates) while commits prefixed with '+' are in 'next'.
It probably is a good point to stop taking new topics and start
switching our focus to fixing bugs in the topics already in 'master'.
Here are the repositories that have my integration branches:
With maint, master, next, pu, todo, html and man:
git://git.kernel.org/pub/scm/git/git.git
git://repo.or.cz/alt-git.git
https://code.google.com/p/git-core/
https://github.com/git/git
With only maint, master, html and man:
git://git.sourceforge.jp/gitroot/git-core/git.git
git://git-core.git.sourceforge.net/gitroot/git-core/git-core
With all the topics and integration branches but not todo, html or man:
https://github.com/gitster/git
By the way, I am planning to stop pushing the generated documentation
branches to the above repositories in the near term, as they are not
sources. The only reason the source repository at k.org has hosted these
branches was because it was the only repository over there that was
writable by me; it was an ugly historical and administrative workaround
and not a demonstration of the best practice.
They are pushed to their own separate repositories instead:
git://git.kernel.org/pub/scm/git/git-{htmldocs,manpages}.git/
git://repo.or.cz/git-{htmldocs,manpages}.git/
https://code.google.com/p/git-{htmldocs,manpages}.git/
https://github.com/gitster/git-{htmldocs,manpages}.git/
--------------------------------------------------
[New Topics]
* nd/pretty-commit-log-message (2011-10-23) 2 commits
- pretty.c: use original commit message if reencoding fails
- pretty.c: free get_header() return value
--------------------------------------------------
[Graduated to "master"]
* cn/doc-config-bare-subsection (2011-10-16) 1 commit
(merged to 'next' on 2011-10-17 at a6412d4)
+ Documentation: update [section.subsection] to reflect what git does
* jc/broken-ref-dwim-fix (2011-10-19) 3 commits
(merged to 'next' on 2011-10-19 at 40cad95)
+ resolve_ref(): report breakage to the caller without warning
+ resolve_ref(): expose REF_ISBROKEN flag
+ refs.c: move dwim_ref()/dwim_log() from sha1_name.c
(this branch is tangled with jc/check-ref-format-fixup.)
This only takes good bits from the failed jc/check-ref-format-fixup topic
and implements saner workaround for the recent breakage on the 'master'.
* jc/maint-remove-renamed-ref (2011-10-12) 1 commit
(merged to 'next' on 2011-10-12 at 819c3e4)
+ branch -m/-M: remove undocumented RENAMED-REF
* jc/make-tags (2011-10-18) 1 commit
(merged to 'next' on 2011-10-19 at b0b91bf)
+ Makefile: ask "ls-files" to list source files if available
* jc/match-refs-clarify (2011-09-12) 2 commits
(merged to 'next' on 2011-10-19 at b295e1e)
+ rename "match_refs()" to "match_push_refs()"
+ send-pack: typofix error message
* jc/unseekable-bundle (2011-10-13) 2 commits
(merged to 'next' on 2011-10-19 at 2978ee0)
+ bundle: add parse_bundle_header() helper function
+ bundle: allowing to read from an unseekable fd
* jk/daemon-msgs (2011-10-15) 1 commit
(merged to 'next' on 2011-10-15 at 415cf53)
+ daemon: give friendlier error messages to clients
(this branch is used by cb/daemon-permission-errors.)
* jk/maint-pack-objects-compete-with-delete (2011-10-14) 2 commits
(merged to 'next' on 2011-10-15 at 49479e4)
+ downgrade "packfile cannot be accessed" errors to warnings
+ pack-objects: protect against disappearing packs
* mh/ref-api (2011-10-16) 7 commits
(merged to 'next' on 2011-10-17 at 219000f)
+ clear_ref_cache(): inline function
+ write_ref_sha1(): only invalidate the loose ref cache
+ clear_ref_cache(): extract two new functions
+ clear_ref_cache(): rename parameter
+ invalidate_ref_cache(): expose this function in the refs API
+ invalidate_ref_cache(): take the submodule as parameter
+ invalidate_ref_cache(): rename function from invalidate_cached_refs()
(this branch is used by mh/ref-api-2 and mh/ref-api-3.)
* ph/transport-with-gitfile (2011-10-11) 5 commits
(merged to 'next' on 2011-10-12 at 6d58417)
+ Fix is_gitfile() for files too small or larger than PATH_MAX to be a gitfile
(merged to 'next' on 2011-10-06 at 891b8b6)
+ Add test showing git-fetch groks gitfiles
+ Teach transport about the gitfile mechanism
+ Learn to handle gitfiles in enter_repo
+ enter_repo: do not modify input
* po/insn-editor (2011-10-17) 1 commit
(merged to 'next' on 2011-10-19 at cbf5e0b)
+ "rebase -i": support special-purpose editor to edit insn sheet
* pw/p4-update (2011-10-17) 6 commits
(merged to 'next' on 2011-10-17 at f69f6cc)
+ git-p4: handle files with shell metacharacters
+ git-p4: keyword flattening fixes
+ git-p4: stop ignoring apple filetype
+ git-p4: recognize all p4 filetypes
+ git-p4: handle utf16 filetype properly
+ git-p4 tests: refactor and cleanup
* sc/difftool-skip (2011-10-14) 2 commits
(merged to 'next' on 2011-10-14 at b91c581)
+ t7800: avoid arithmetic expansion notation
(merged to 'next' on 2011-10-11 at 38d7e84)
+ git-difftool: allow skipping file by typing 'n' at prompt
* ss/inet-ntop (2011-10-18) 1 commit
(merged to 'next' on 2011-10-19 at 85469f6)
+ inet_ntop.c: Work around GCC 4.6's detection of uninitialized variables
--------------------------------------------------
[Stalled]
* hv/submodule-merge-search (2011-10-13) 4 commits
- submodule.c: make two functions static
- allow multiple calls to submodule merge search for the same path
- push: Don't push a repository with unpushed submodules
- push: teach --recurse-submodules the on-demand option
What the topic aims to achieve may make sense, but the implementation
looked somewhat suboptimal.
The fix-up at the tip queued on fg/submodule-auto-push topic has been
moved to this topic.
* sr/transport-helper-fix-rfc (2011-07-19) 2 commits
- t5800: point out that deleting branches does not work
- t5800: document inability to push new branch with old content
Perhaps 281eee4 (revision: keep track of the end-user input from the
command line, 2011-08-25) would help.
* jc/lookup-object-hash (2011-08-11) 6 commits
- object hash: replace linear probing with 4-way cuckoo hashing
- object hash: we know the table size is a power of two
- object hash: next_size() helper for readability
- pack-objects --count-only
- object.c: remove duplicated code for object hashing
- object.c: code movement for readability
I do not think there is anything fundamentally wrong with this series, but
the risk of breakage far outweighs observed performance gain in one
particular workload.
* jc/verbose-checkout (2011-10-16) 2 commits
- checkout -v: give full status output after switching branches
- checkout: move the local changes report to the end
This is just to leave a record that the reason why we do not do this not
because we are incapable of coding this, but because it is not a good idea
to do this. I suspect people who are new to git that might think they need
it would soon realize the don't.
Will keep in 'pu' as a showcase for a while and then will drop.
--------------------------------------------------
[Cooking]
* tc/submodule-clone-name-detection (2011-10-21) 2 commits
(merged to 'next' on 2011-10-23 at c18af03)
+ submodule::module_clone(): silence die() message from module_name()
+ submodule: whitespace fix
"git submodule clone" used to show unnecessary error message when
submodule mapping from name to path is not found in .gitmodules file.
Will merge to 'master'.
* jm/maint-gitweb-filter-forks-fix (2011-10-21) 1 commit
(merged to 'next' on 2011-10-21 at debedcd)
+ gitweb: fix regression when filtering out forks
Will merge to 'master' shortly.
* lh/gitweb-site-html-head (2011-10-21) 1 commit
(merged to 'next' on 2011-10-23 at 65075df)
+ gitweb: provide a way to customize html headers
Will merge to 'master' shortly.
* mh/ref-api-3 (2011-10-19) 11 commits
(merged to 'next' on 2011-10-23 at 92e2d35)
+ is_refname_available(): reimplement using do_for_each_ref_in_array()
+ names_conflict(): simplify implementation
+ names_conflict(): new function, extracted from is_refname_available()
+ repack_without_ref(): reimplement using do_for_each_ref_in_array()
+ do_for_each_ref_in_array(): new function
+ do_for_each_ref(): correctly terminate while processesing extra_refs
+ add_ref(): take a (struct ref_entry *) parameter
+ create_ref_entry(): extract function from add_ref()
+ parse_ref_line(): add a check that the refname is properly formatted
+ repack_without_ref(): remove temporary
+ Rename another local variable name -> refname
(this branch uses mh/ref-api-2.)
* mm/mediawiki-author-fix (2011-10-20) 1 commit
(merged to 'next' on 2011-10-23 at 9f85b67)
+ git-remote-mediawiki: don't include HTTP login/password in author
Will merge to 'master' shortly.
* rr/revert-cherry-pick (2011-10-23) 5 commits
- revert: simplify communicating command-line arguments
- revert: allow mixed pick and revert instructions
- revert: make commit subjects in insn sheet optional
- revert: simplify getting commit subject in format_todo()
- revert: free msg in format_todo()
The internals of "git revert/cherry-pick" has been further refactored to
serve as the basis for the sequencer.
Will merge to 'next'.
* jn/libperl-git-config (2011-10-21) 2 commits
(merged to 'next' on 2011-10-21 at 76e2d4b)
+ Add simple test for Git::config_path() in t/t9700-perl-git.sh
+ libperl-git: refactor Git::config_*
Will merge to 'master' shortly.
* jc/check-ref-format-fixup (2011-10-19) 2 commits
(merged to 'next' on 2011-10-19 at 98981be)
+ Revert "Restrict ref-like names immediately below $GIT_DIR"
(merged to 'next' on 2011-10-15 at 8e89bc5)
+ Restrict ref-like names immediately below $GIT_DIR
This became a no-op except for the bottom one which is part of the other
topic now.
Will discard once the other topic graduates to 'master'.
* cb/daemon-permission-errors (2011-10-17) 2 commits
- daemon: report permission denied error to clients
- daemon: add tests
The tip commit might be loosening things a bit too much.
Will keep in 'pu' until hearing a convincing argument for the patch.
* kk/gitweb-side-by-side-diff (2011-10-17) 2 commits
- gitweb: add a feature to show side-by-side diff
- gitweb: change format_diff_line() to remove leading SP from $diff_class
Fun.
Will keep in 'pu' until the planned re-roll comes.
* mh/ref-api-2 (2011-10-17) 14 commits
(merged to 'next' on 2011-10-19 at cc89f0e)
+ resolve_gitlink_ref_recursive(): change to work with struct ref_cache
+ Pass a (ref_cache *) to the resolve_gitlink_*() helper functions
+ resolve_gitlink_ref(): improve docstring
+ get_ref_dir(): change signature
+ refs: change signatures of get_packed_refs() and get_loose_refs()
+ is_dup_ref(): extract function from sort_ref_array()
+ add_ref(): add docstring
+ parse_ref_line(): add docstring
+ is_refname_available(): remove the "quiet" argument
+ clear_ref_array(): rename from free_ref_array()
+ refs: rename parameters result -> sha1
+ refs: rename "refname" variables
+ struct ref_entry: document name member
+ cache.h: add comments for git_path() and git_path_submodule()
(this branch is used by mh/ref-api-3.)
It is either merge this quickly to 'master' and hope there won't be any
more unexpected breakage that forces us to delay the release, or hold it
on 'next' until the next cycle. I am inclined to do the former, but not
quite ready to commit to it yet.
* dm/pack-objects-update (2011-10-20) 4 commits
- pack-objects: don't traverse objects unnecessarily
- pack-objects: rewrite add_descendants_to_write_order() iteratively
- pack-objects: use unsigned int for counter and offset values
- pack-objects: mark add_to_write_order() as inline
Need to re-read this before deciding what to do; it came a bit too late in
the cycle for a series that touches a seriously important part of the
system.
* jk/git-tricks (2011-10-21) 3 commits
(merged to 'next' on 2011-10-23 at 7c9bf71)
+ completion: match ctags symbol names in grep patterns
+ contrib: add git-jump script
+ contrib: add diff highlight script
* jc/signed-commit (2011-10-21) 7 commits
(merged to 'next' on 2011-10-23 at 03eec25)
+ pretty: %G[?GS] placeholders
+ parse_signed_commit: really use the entire commit log message
+ test "commit -S" and "log --show-signature"
+ t7004: extract generic "GPG testing" bits
+ log: --show-signature
+ commit: teach --gpg-sign option
+ Split GPG interface into its own helper library
This is to replace the earlier "signed push" experiments.
Will keep in 'next' during this cycle.
* sg/complete-refs (2011-10-21) 9 commits
- completion: remove broken dead code from __git_heads() and __git_tags()
- completion: fast initial completion for config 'remote.*.fetch' value
- completion: improve ls-remote output filtering in __git_refs_remotes()
- completion: query only refs/heads/ in __git_refs_remotes()
- completion: support full refs from remote repositories
- completion: improve ls-remote output filtering in __git_refs()
- completion: make refs completion consistent for local and remote repos
- completion: optimize refs completion
- completion: document __gitcomp()
Will merge to 'next' but won't merge further until an Ack or two from
people who have worked on the completion in the past comes.
* cn/fetch-prune (2011-10-15) 5 commits
(merged to 'next' on 2011-10-16 at 02a449e)
+ fetch: treat --tags like refs/tags/*:refs/tags/* when pruning
+ fetch: honor the user-provided refspecs when pruning refs
+ remote: separate out the remote_find_tracking logic into query_refspecs
+ t5510: add tests for fetch --prune
+ fetch: free all the additional refspecs
"git fetch --prune" used to prune remote tracking branches by comparing
what was actually fetched and what was configured to be fetched, which was
wrong.
Will merge to 'master' shortly.
* jc/request-pull-show-head-4 (2011-10-15) 11 commits
(merged to 'next' on 2011-10-15 at 7e340ff)
+ fmt-merge-msg.c: Fix an "dubious one-bit signed bitfield" sparse error
(merged to 'next' on 2011-10-10 at 092175e)
+ environment.c: Fix an sparse "symbol not declared" warning
+ builtin/log.c: Fix an "Using plain integer as NULL pointer" warning
(merged to 'next' on 2011-10-07 at fcaeca0)
+ fmt-merge-msg: use branch.$name.description
(merged to 'next' on 2011-10-06 at fa5e0fe)
+ request-pull: use the branch description
+ request-pull: state what commit to expect
+ request-pull: modernize style
+ branch: teach --edit-description option
+ format-patch: use branch description in cover letter
+ branch: add read_branch_desc() helper function
+ Merge branch 'bk/ancestry-path' into jc/branch-desc
Allow setting "description" for branches and use it to help communications
between humans in various workflow elements.
Will keep in 'next' during this cycle.
^ permalink raw reply
* Re: [PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()
From: Michael Haggerty @ 2011-10-24 11:58 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips
In-Reply-To: <4E9FD1C3.3090302@alum.mit.edu>
On 10/20/2011 09:46 AM, Michael Haggerty wrote:
> On 10/20/2011 03:40 AM, Junio C Hamano wrote:
>> Hmm, why is this patch and only this one in the series full of whitespace
>> violations? Did you use a different settings or something?
>
> This happens rarely; I don't know why. Maybe I copy-pasted snippets
> from a view in an application that expanded the tabs. [...]
Now I think I know how this happened. When "git diff"'s output goes to
a TTY, it passes its output through the pager. The default pager, less,
seems to convert tabs into spaces. I probably copy-pasted some output
of diff into my editor then removed the first column of '+' characters.
Just another reason why tabs are evil...
:-)
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply
* Re: [PATCH 00/22] Refactor to accept NUL in commit messages
From: Štěpán Němec @ 2011-10-24 11:09 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy
Cc: Junio C Hamano, git, Jeff King, Ævar Arnfjörð
In-Reply-To: <CACsJy8AsfQnS3L1fabzB-z7BdH=jvB=XNnmP2RZu0qp7C1uGYQ@mail.gmail.com>
On Mon, 24 Oct 2011 07:10:08 +0200
Nguyen Thai Ngoc Duy wrote:
> This is argument for the sake of argument because I don't use utf-16
> and do not care much. UTF-16 can have more code points and some may
> prefer utf-16 to utf-8.
I suspect this is really tangential to this thread, but I can't make
much sense of that last sentence -- if you meant that UTF-16 is somehow
more apt at encoding Unicode code points than UTF-8, then that's not the
case. Both can represent all Unicode characters. If anything, things are
_more_, not less complicated in UTF-16, which apart from the NUL and
endianness complications has to jump through the "surrogate pairs" hoop
for code points bigger than U+FFFF (so you'll actually find many apps
with buggy UTF-16 implementation which break for those code points,
unlike when using UTF-8).
--
Štěpán
^ permalink raw reply
* Re: Possible diff regression in v1.7.6-473-g27af01d
From: Tay Ray Chuan @ 2011-10-24 10:11 UTC (permalink / raw)
To: Thomas Rast
Cc: Franz Schrober, git@vger.kernel.org, marat@slonopotamus.org,
gitster@pobox.com
In-Reply-To: <201110241138.51448.trast@student.ethz.ch>
On Mon, Oct 24, 2011 at 5:38 PM, Thomas Rast <trast@student.ethz.ch> wrote:
>
> I'm not sure why you call this a regression. For the benefit of
> people who hate saving attachments, you used
>
> $ paste anonymized_orig anonymized_new | xclip
> 0 1
> 0 2
> 0 0
> 0 3
> 4
> 5
> 6
> 7
>
> the old diff was
>
> --- a/anonymized_orig
> +++ b/anonymized_new
> @@ -1,4 +1,8 @@
> -0
> -0
> -0
> -0
> +1
> +2
> +0
> +3
> +4
> +5
> +6
> +7
>
> and the new diff is
>
> --- a/anonymized_orig
> +++ b/anonymized_new
> @@ -1,4 +1,8 @@
> +1
> +2
> 0
> -0
> -0
> -0
> +3
> +4
> +5
> +6
> +7
>
> So the new diff correctly represents the change, and on top of that is
> shorter (by only one line, admittedly). What makes it a regression?
Thanks for inlining it, Thomas.
> Franz Schrober wrote:>> Hi,>>>> I am using git to manage some patches on top of the actual upstream files, but noticed that the result of git-format-patch changed between 4bfe7cb6668c43c1136304bbb17eea1b3ddf0237 and 27af01d552331eacf1ed2671b2b4b6ad4c268106>>>> I've attached two input files (I tried to provide a minimal example... I am not sure if a smaller example is possible but at least both files are smaller than 10 lines) and the results with version 1.7.6.3 and and 1.7.7. The diffs were created using: git diff anonymized_orig anonymized_new>>>> My .gitconfig file is empty.
This has been "fixed" in v1.7.7.1, with 713b85c (Merge branch
'rs/diff-cleanup-records-fix' into maint) - "fixed" in that it gives
back the old behaviour, not that the diff produced is incorrect and
needs fixing.
(I'm running 1.7.7.1.599.g03eec, I get the same diff as diff.1.7.6.3)
--
Cheers,
Ray Chuan
^ permalink raw reply
* Re: Possible diff regression in v1.7.6-473-g27af01d
From: Thomas Rast @ 2011-10-24 9:38 UTC (permalink / raw)
To: Franz Schrober
Cc: git@vger.kernel.org, marat@slonopotamus.org, rctay89@gmail.com,
gitster@pobox.com
In-Reply-To: <1319448227.70497.YahooMailNeo@web29402.mail.ird.yahoo.com>
Franz Schrober wrote:
> Hi,
>
> I am using git to manage some patches on top of the actual upstream files, but noticed that the result of git-format-patch changed between 4bfe7cb6668c43c1136304bbb17eea1b3ddf0237 and 27af01d552331eacf1ed2671b2b4b6ad4c268106
>
> I've attached two input files (I tried to provide a minimal example... I am not sure if a smaller example is possible but at least both files are smaller than 10 lines) and the results with version 1.7.6.3 and and 1.7.7. The diffs were created using: git diff anonymized_orig anonymized_new
>
> My .gitconfig file is empty.
I'm not sure why you call this a regression. For the benefit of
people who hate saving attachments, you used
$ paste anonymized_orig anonymized_new | xclip
0 1
0 2
0 0
0 3
4
5
6
7
the old diff was
--- a/anonymized_orig
+++ b/anonymized_new
@@ -1,4 +1,8 @@
-0
-0
-0
-0
+1
+2
+0
+3
+4
+5
+6
+7
and the new diff is
--- a/anonymized_orig
+++ b/anonymized_new
@@ -1,4 +1,8 @@
+1
+2
0
-0
-0
-0
+3
+4
+5
+6
+7
So the new diff correctly represents the change, and on top of that is
shorter (by only one line, admittedly). What makes it a regression?
--
Thomas Rast
trast@{inf,student}.ethz.ch
^ permalink raw reply
* Possible diff regression in v1.7.6-473-g27af01d
From: Franz Schrober @ 2011-10-24 9:23 UTC (permalink / raw)
To: git@vger.kernel.org
Cc: marat@slonopotamus.org, rctay89@gmail.com, gitster@pobox.com,
franzschrober@yahoo.de
[-- Attachment #1: Type: text/plain, Size: 567 bytes --]
Hi,
I am using git to manage some patches on top of the actual upstream files, but noticed that the result of git-format-patch changed between 4bfe7cb6668c43c1136304bbb17eea1b3ddf0237 and 27af01d552331eacf1ed2671b2b4b6ad4c268106
I've attached two input files (I tried to provide a minimal example... I am not sure if a smaller example is possible but at least both files are smaller than 10 lines) and the results with version 1.7.6.3 and and 1.7.7. The diffs were created using: git diff anonymized_orig anonymized_new
My .gitconfig file is empty.
Thanks
[-- Attachment #2: anonymized_orig --]
[-- Type: application/octet-stream, Size: 8 bytes --]
0
0
0
0
[-- Attachment #3: anonymized_new --]
[-- Type: application/octet-stream, Size: 16 bytes --]
1
2
0
3
4
5
6
7
[-- Attachment #4: diff.1.7.6.3 --]
[-- Type: application/octet-stream, Size: 171 bytes --]
diff --git a/anonymized_orig b/anonymized_new
index 44e0be8..ad0f859 100644
--- a/anonymized_orig
+++ b/anonymized_new
@@ -1,4 +1,8 @@
-0
-0
-0
-0
+1
+2
+0
+3
+4
+5
+6
+7
[-- Attachment #5: diff.1.7.7 --]
[-- Type: application/octet-stream, Size: 168 bytes --]
diff --git a/anonymized_orig b/anonymized_new
index 44e0be8..ad0f859 100644
--- a/anonymized_orig
+++ b/anonymized_new
@@ -1,4 +1,8 @@
+1
+2
0
-0
-0
-0
+3
+4
+5
+6
+7
^ permalink raw reply related
* Re: [PATCH] read-cache.c: fix index memory allocation
From: Junio C Hamano @ 2011-10-24 7:28 UTC (permalink / raw)
To: René Scharfe; +Cc: Jeff King, John Hsing, Matthieu Moy, git
In-Reply-To: <4EA4B8E7.5070106@lsrfire.ath.cx>
René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> t/t7510-status-index.sh | 50 +++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 53 insertions(+), 3 deletions(-)
> create mode 100755 t/t7510-status-index.sh
> diff --git a/t/t7510-status-index.sh b/t/t7510-status-index.sh
> new file mode 100755
> index 0000000..bca359d
> --- /dev/null
> +++ b/t/t7510-status-index.sh
> @@ -0,0 +1,50 @@
Hmm, I cannot seem to make this fail this test without the fix on my
Fedora 14 i686 VM when applied to v1.7.6.4 (estimation code originates
cf55870 back in v1.7.6.1 days), but it does break on 'master'.
By the way, I'll move this to 7511.
Also would a patch like this help?
-- >8 --
Subject: [PATCH] read_index(): die on estimation error
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
read-cache.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/read-cache.c b/read-cache.c
index 0a64103..2926615 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1270,6 +1270,7 @@ int read_index_from(struct index_state *istate, const char *path)
int fd, i;
struct stat st;
unsigned long src_offset, dst_offset;
+ size_t bulk_alloc_size;
struct cache_header *hdr;
void *mmap;
size_t mmap_size;
@@ -1315,7 +1316,8 @@ int read_index_from(struct index_state *istate, const char *path)
* has room for a few more flags, we can allocate using the same
* index size
*/
- istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
+ bulk_alloc_size = estimate_cache_size(mmap_size, istate->cache_nr);
+ istate->alloc = xmalloc(bulk_alloc_size);
istate->initialized = 1;
src_offset = sizeof(*hdr);
@@ -1331,7 +1333,9 @@ int read_index_from(struct index_state *istate, const char *path)
src_offset += ondisk_ce_size(ce);
dst_offset += ce_size(ce);
+ if (bulk_alloc_size <= dst_offset)
+ die("cache size estimation error");
}
istate->timestamp.sec = st.st_mtime;
istate->timestamp.nsec = ST_MTIME_NSEC(st);
--
1.7.7.1.504.gcc718
^ permalink raw reply related
* Re: [PATCH] read-cache.c: fix index memory allocation
From: Junio C Hamano @ 2011-10-24 7:07 UTC (permalink / raw)
To: René Scharfe; +Cc: Jeff King, John Hsing, Matthieu Moy, git
In-Reply-To: <4EA4B8E7.5070106@lsrfire.ath.cx>
Thanks.
This approach may be the most appropriate for the maintenance track, but
for the purpose of going forward, I wonder if we really want to keep the
"estimate and allocate a large pool, and carve out individual pieces".
This bulk-allocate dates back to the days when we didn't have ondisk vs
incore representation differences, IIRC, and as the result we deliberately
leak cache entries whenever an entry in the index is replaced with a new
one. Does the overhead to allocate individually really kill us that much
for say a tree with 30k files in it?
^ permalink raw reply
* Re: [PATCH] Reindent closing bracket using tab instead of spaces
From: Junio C Hamano @ 2011-10-24 6:56 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy; +Cc: git
In-Reply-To: <1319430291-12612-1-git-send-email-pclouds@gmail.com>
Thanks.
^ permalink raw reply
* [PATCH/WIP 11/11] dir.c: remove dead code after read_directory() rewrite
From: Nguyễn Thái Ngọc Duy @ 2011-10-24 6:36 UTC (permalink / raw)
To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1319438176-7304-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
dir.c | 121 -----------------------------------------------------------------
dir.h | 3 --
2 files changed, 0 insertions(+), 124 deletions(-)
diff --git a/dir.c b/dir.c
index 2946b2d..4094962 100644
--- a/dir.c
+++ b/dir.c
@@ -11,11 +11,6 @@
#include "tree-walk.h"
#include "string-list.h"
-struct path_simplify {
- int len;
- const char *path;
-};
-
static int read_directory_recursive(struct dir_struct *dir,
struct strbuf *base,
int check_only,
@@ -604,15 +599,6 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
return dir->entries[dir->nr++] = dir_entry_new(pathname, len);
}
-struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
-{
- if (!cache_name_is_other(pathname, len))
- return NULL;
-
- ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);
- return dir->ignored[dir->ignored_nr++] = dir_entry_new(pathname, len);
-}
-
/* Read and convert directory to tree object (with invalid SHA-1) */
static void* dir_to_tree(struct strbuf *path, unsigned long *size)
{
@@ -845,31 +831,6 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
}
/*
- * This is an inexact early pruning of any recursive directory
- * reading - if the path cannot possibly be in the pathspec,
- * return true, and we'll skip it early.
- */
-static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify)
-{
- if (simplify) {
- for (;;) {
- const char *match = simplify->path;
- int len = simplify->len;
-
- if (!match)
- break;
- if (len > pathlen)
- len = pathlen;
- if (!memcmp(path, match, len))
- return 0;
- simplify++;
- }
- return 1;
- }
- return 0;
-}
-
-/*
* This function flags pathspecs that are completely excluded, which
* usually means an input mistake. In other words, if all matched
* _files_ of a pathspec are excluded, flag the pathspec.
@@ -1087,88 +1048,6 @@ static int cmp_name(const void *p1, const void *p2)
e2->name, e2->len);
}
-/*
- * Return the length of the "simple" part of a path match limiter.
- */
-static int simple_length(const char *match)
-{
- int len = -1;
-
- for (;;) {
- unsigned char c = *match++;
- len++;
- if (c == '\0' || is_glob_special(c))
- return len;
- }
-}
-
-static struct path_simplify *create_simplify(const char **pathspec)
-{
- int nr, alloc = 0;
- struct path_simplify *simplify = NULL;
-
- if (!pathspec)
- return NULL;
-
- for (nr = 0 ; ; nr++) {
- const char *match;
- if (nr >= alloc) {
- alloc = alloc_nr(alloc);
- simplify = xrealloc(simplify, alloc * sizeof(*simplify));
- }
- match = *pathspec++;
- if (!match)
- break;
- simplify[nr].path = match;
- simplify[nr].len = simple_length(match);
- }
- simplify[nr].path = NULL;
- simplify[nr].len = 0;
- return simplify;
-}
-
-static void free_simplify(struct path_simplify *simplify)
-{
- free(simplify);
-}
-
-#if 0
-static int treat_leading_path(struct dir_struct *dir,
- const char *path, int len,
- const struct path_simplify *simplify)
-{
- char pathbuf[PATH_MAX];
- int baselen, blen;
- const char *cp;
-
- while (len && path[len - 1] == '/')
- len--;
- if (!len)
- return 1;
- baselen = 0;
- while (1) {
- cp = path + baselen + !!baselen;
- cp = memchr(cp, '/', path + len - cp);
- if (!cp)
- baselen = len;
- else
- baselen = cp - path;
- memcpy(pathbuf, path, baselen);
- pathbuf[baselen] = '\0';
- if (!is_directory(pathbuf))
- return 0;
- if (simplify_away(pathbuf, baselen, simplify))
- return 0;
- blen = baselen;
- if (treat_one_path(dir, pathbuf, &blen, simplify,
- DT_DIR, NULL) == path_ignored)
- return 0; /* do not recurse into it */
- if (len <= baselen)
- return 1; /* finished checking */
- }
-}
-#endif
-
int read_directory(struct dir_struct *dir, const char *path, int len,
const char **pathspec)
{
diff --git a/dir.h b/dir.h
index 362d7b1..7a7d818 100644
--- a/dir.h
+++ b/dir.h
@@ -33,7 +33,6 @@ struct exclude_stack {
struct dir_struct {
int nr, alloc;
- int ignored_nr, ignored_alloc;
enum {
DIR_SHOW_IGNORED = 1<<0,
DIR_SHOW_OTHER_DIRECTORIES = 1<<1,
@@ -42,7 +41,6 @@ struct dir_struct {
DIR_COLLECT_IGNORED = 1<<4
} flags;
struct dir_entry **entries;
- struct dir_entry **ignored;
int *useful;
/* Include info (a joint of ps1 and ps2) */
@@ -82,7 +80,6 @@ extern int read_directory(struct dir_struct *, const char *path, int len, const
extern int excluded_from_list(const char *pathname, int pathlen, const char *basename,
int *dtype, struct exclude_list *el);
extern int excluded(struct dir_struct *, const char *, int *);
-struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
char **buf_p, struct exclude_list *which, int check_index);
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
--
1.7.3.1.256.g2539c.dirty
^ permalink raw reply related
* [PATCH/WIP 10/11] read-dir: stop using path_simplify code in favor of tree_entry_interesting()
From: Nguyễn Thái Ngọc Duy @ 2011-10-24 6:36 UTC (permalink / raw)
To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1319438176-7304-1-git-send-email-pclouds@gmail.com>
Current code tries to find a prefix set of given pathspecs and filter
on the set. Call sites are supposed to do exact pathspec matching
again to remove unmatched entries (but matches the prefix set).
This patch makes read_directory() use tree_entry_interesting()
directly, thus remove the need to filter again by call sites (although
call sites are untouched in this patch).
A less intrusive way would be to use match_pathspec_depth(), but I'd
rather reduce the use of that function and eventually remove it, so we
only have to maintain pathspec matching at one place:
tree_entry_interesting().
In order to make use of tree_entry_interesting(), directory content
from readdir() must be converted to tree object format, which means we
have to read all items of a directory at once and sort it. If the
directory is large, it may become expensive operation. But again,
current code does nothing to stop reading directory early, so nothing
is lost.
ignored_nr and ignored[] are not longer filled. read_directory() users
are supposed to use useful[] instead.
Many functions are left unused in this patch to avoid clutter up the
patch. They will be removed later.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/add.c | 22 +++--
dir.c | 317 ++++++++++++++++++++++++++++++++++++++-------------------
dir.h | 5 +
tree-walk.c | 2 +
4 files changed, 236 insertions(+), 110 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index 23ad4b8..92ba3d4 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -307,7 +307,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
static struct lock_file lock_file;
static const char ignore_error[] =
-N_("The following paths are ignored by one of your .gitignore files:\n");
+N_("The following pathspecs are ignored by one of your .gitignore files:\n");
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
static int ignore_add_errors, addremove, intent_to_add;
@@ -342,12 +342,20 @@ static int add_files(struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
- if (dir->ignored_nr) {
- fprintf(stderr, _(ignore_error));
- for (i = 0; i < dir->ignored_nr; i++)
- fprintf(stderr, "%s\n", dir->ignored[i]->name);
- fprintf(stderr, _("Use -f if you really want to add them.\n"));
- die(_("no files added"));
+ if (dir->useful) {
+ int show_header = 0;
+ for (i = 0; i < dir->ps2.nr; i++)
+ if (!dir->useful[i]) {
+ if (!show_header) {
+ fprintf(stderr, _(ignore_error));
+ show_header = 1;
+ }
+ fprintf(stderr, "%s\n", dir->ps2.items[i].match);
+ }
+ if (show_header) {
+ fprintf(stderr, _("Use -f if you really want to add them.\n"));
+ die(_("no files added"));
+ }
}
for (i = 0; i < dir->nr; i++)
diff --git a/dir.c b/dir.c
index 0a78d00..2946b2d 100644
--- a/dir.c
+++ b/dir.c
@@ -8,14 +8,18 @@
#include "cache.h"
#include "dir.h"
#include "refs.h"
+#include "tree-walk.h"
+#include "string-list.h"
struct path_simplify {
int len;
const char *path;
};
-static int read_directory_recursive(struct dir_struct *dir, const char *path, int len,
- int check_only, const struct path_simplify *simplify);
+static int read_directory_recursive(struct dir_struct *dir,
+ struct strbuf *base,
+ int check_only,
+ enum interesting match);
static int get_dtype(struct dirent *de, const char *path, int len);
/* helper string functions with support for the ignore_case flag */
@@ -609,6 +613,93 @@ struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname,
return dir->ignored[dir->ignored_nr++] = dir_entry_new(pathname, len);
}
+/* Read and convert directory to tree object (with invalid SHA-1) */
+static void* dir_to_tree(struct strbuf *path, unsigned long *size)
+{
+ int pathlen = path->len;
+ DIR *fdir = opendir(pathlen ? path->buf : ".");
+ struct string_list paths = STRING_LIST_INIT_DUP;
+ struct dirent *de;
+ char *tree, *p;
+ int i,dtype;
+
+ if (!fdir)
+ return NULL;
+
+ *size = 0;
+ while ((de = readdir(fdir)) != NULL) {
+ int namelen = strlen(de->d_name);
+ struct string_list_item *item;
+ const char *mode = NULL;
+
+ if (is_dot_or_dotdot(de->d_name) ||
+ !strcmp(de->d_name, ".git") ||
+ /* Ignore overly long pathnames! */
+ namelen + pathlen + 8 > PATH_MAX)
+ continue;
+
+ strbuf_add(path, de->d_name, namelen);
+ dtype = get_dtype(de, path->buf, path->len);
+ strbuf_setlen(path, pathlen);
+
+ switch (dtype) {
+ case DT_DIR: mode = "040000 "; break;
+ case DT_REG: mode = "100644 "; break;
+ case DT_LNK: mode = "120000 "; break;
+ default: continue;
+ }
+ item = string_list_insert(&paths, de->d_name);
+ item->util = (void*)mode;
+ /* 100644 SPC path NUL SHA-1 */
+ *size += 6 + 1 + namelen + 1 + 20;
+ }
+ closedir(fdir);
+
+ tree = xmalloc(*size);
+ for (i = 0, p = tree;i < paths.nr; i++) {
+ int len = strlen(paths.items[i].string) + 1;
+ if (!paths.items[i].util ||
+ strlen(paths.items[i].util) != 7)
+ die("BUG: util should contain a mode");
+ memcpy(p, paths.items[i].util, 7);
+ p += 7;
+ memcpy(p, paths.items[i].string, len);
+ p += len;
+ /* we don't need valid SHA-1 for tree_entry_interesting() */
+ memcpy(p, "\xbb\xaa\xdd\xbb\xaa\xdd\xbb\xaa\xdd", 9);
+ p += 20;
+ }
+ string_list_clear(&paths, 0);
+ return tree;
+}
+
+static enum interesting match_both_pathspecs(struct dir_struct *dir,
+ struct strbuf *base,
+ const struct name_entry *ne)
+{
+ int i;
+ enum interesting ret1, ret2;
+
+ /* ps1 contains the base path, no need to care about it */
+ for (i = 0; i < dir->ps2.nr; i++)
+ dir->ps2.items[i].useful = 0;
+
+ ret1 = tree_entry_interesting(ne, base, 0, &dir->ps1);
+ if (ret1 <= 0)
+ return ret1;
+ ret2 = tree_entry_interesting(ne, base, 0, &dir->ps2);
+ if (ret2 <= 0)
+ return ret2;
+
+ if (ret1 == all_entries_interesting && ret2 == all_entries_interesting)
+ return all_entries_interesting;
+ else if ((ret1 == entry_matched || ret1 == all_entries_interesting) &&
+ (ret2 == entry_matched || ret2 == all_entries_interesting))
+ return entry_matched;
+ else
+ return entry_interesting;
+}
+
enum exist_status {
index_nonexistent = 0,
index_directory,
@@ -722,11 +813,10 @@ enum directory_treatment {
};
static enum directory_treatment treat_directory(struct dir_struct *dir,
- const char *dirname, int len,
- const struct path_simplify *simplify)
+ struct strbuf *dirname)
{
/* The "len-1" is to strip the final '/' */
- switch (directory_exists_in_index(dirname, len-1)) {
+ switch (directory_exists_in_index(dirname->buf, dirname->len-1)) {
case index_directory:
return recurse_into_directory;
@@ -740,7 +830,7 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
break;
if (!(dir->flags & DIR_NO_GITLINKS)) {
unsigned char sha1[20];
- if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0)
+ if (resolve_gitlink_ref(dirname->buf, "HEAD", sha1) == 0)
return show_directory;
}
return recurse_into_directory;
@@ -749,7 +839,7 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
/* This is the "show_other_directories" case */
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
return show_directory;
- if (!read_directory_recursive(dir, dirname, len, 1, simplify))
+ if (!read_directory_recursive(dir, dirname, 1, entry_not_interesting))
return ignore_directory;
return show_directory;
}
@@ -780,31 +870,35 @@ static int simplify_away(const char *path, int pathlen, const struct path_simpli
}
/*
- * This function tells us whether an excluded path matches a
- * list of "interesting" pathspecs. That is, whether a path matched
- * by any of the pathspecs could possibly be ignored by excluding
- * the specified path. This can happen if:
+ * This function flags pathspecs that are completely excluded, which
+ * usually means an input mistake. In other words, if all matched
+ * _files_ of a pathspec are excluded, flag the pathspec.
*
- * 1. the path is mentioned explicitly in the pathspec
+ * The negated version would be: if any of matched files (by pathspec
+ * X) are not excluded, pathspec X is clear, which is exactly what
+ * this function does.
*
- * 2. the path is a directory prefix of some element in the
- * pathspec
+ * This function ignores dir->ps1 because that contains exactly one
+ * pathspec item: the path base. No need to worry about that.
*/
-static int exclude_matches_pathspec(const char *path, int len,
- const struct path_simplify *simplify)
+static void mark_useful(struct dir_struct *dir,
+ const char *path, int len,
+ int dtype,
+ struct pathspec *ps, int exclude,
+ enum interesting match)
{
- if (simplify) {
- for (; simplify->path; simplify++) {
- if (len == simplify->len
- && !memcmp(path, simplify->path, len))
- return 1;
- if (len < simplify->len
- && simplify->path[len] == '/'
- && !memcmp(path, simplify->path, len))
- return 1;
- }
- }
- return 0;
+ int i;
+ if (!(dir->flags & DIR_COLLECT_IGNORED))
+ return;
+ /* half-matches (eg. prefix matches) do not count as useful */
+ if (match != all_entries_interesting && match != entry_matched)
+ return;
+ if (exclude && cache_name_is_other(path, len))
+ return;
+
+ for (i = 0; i < ps->nr; i++)
+ if (ps->items[i].useful)
+ dir->useful[i] = 1;
}
static int get_index_dtype(const char *path, int len)
@@ -872,15 +966,24 @@ enum path_treatment {
path_recurse
};
-static enum path_treatment treat_one_path(struct dir_struct *dir,
- char *path, int *len,
- const struct path_simplify *simplify,
- int dtype, struct dirent *de)
+/* base is modified to contain ne */
+static int treat_path(struct dir_struct *dir,
+ struct strbuf *base, const struct name_entry *ne,
+ enum interesting match)
{
- int exclude = excluded(dir, path, &dtype);
- if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
- && exclude_matches_pathspec(path, *len, simplify))
- dir_add_ignored(dir, path, *len);
+ int exclude, dtype;
+
+ strbuf_add(base, ne->path, tree_entry_len(ne));
+
+ /* It does not matter DT_REG or something else, excluded()
+ * only cares if it's DT_DIR or not */
+ dtype = S_ISDIR(ne->mode) ? DT_DIR : DT_REG;
+ exclude = excluded(dir, base->buf, &dtype);
+
+ /* intermediate directory match does not count */
+ if (dtype == DT_REG)
+ mark_useful(dir, base->buf, base->len, dtype,
+ &dir->ps2, exclude, match);
/*
* Excluded? If we don't explicitly want to show
@@ -889,9 +992,6 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
return path_ignored;
- if (dtype == DT_UNKNOWN)
- dtype = get_dtype(de, path, *len);
-
/*
* Do we want to see just the ignored files?
* We still need to recurse into directories,
@@ -899,17 +999,13 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
* directory may contain files that we do..
*/
if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
- if (dtype != DT_DIR)
+ if (!S_ISDIR(ne->mode))
return path_ignored;
}
- switch (dtype) {
- default:
- return path_ignored;
- case DT_DIR:
- memcpy(path + *len, "/", 2);
- (*len)++;
- switch (treat_directory(dir, path, *len, simplify)) {
+ if (S_ISDIR(ne->mode)) {
+ strbuf_addch(base, '/');
+ switch (treat_directory(dir, base)) {
case show_directory:
if (exclude != !!(dir->flags
& DIR_SHOW_IGNORED))
@@ -920,38 +1016,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
case ignore_directory:
return path_ignored;
}
- break;
- case DT_REG:
- case DT_LNK:
- break;
+
+ /* path_handled for dirs, must be gitlinks */
+ mark_useful(dir, base->buf, base->len, dtype,
+ &dir->ps2, exclude, match);
}
return path_handled;
}
-static enum path_treatment treat_path(struct dir_struct *dir,
- struct dirent *de,
- char *path, int path_max,
- int baselen,
- const struct path_simplify *simplify,
- int *len)
-{
- int dtype;
-
- if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git"))
- return path_ignored;
- *len = strlen(de->d_name);
- /* Ignore overly long pathnames! */
- if (*len + baselen + 8 > path_max)
- return path_ignored;
- memcpy(path + baselen, de->d_name, *len + 1);
- *len += baselen;
- if (simplify_away(path, *len, simplify))
- return path_ignored;
-
- dtype = DTYPE(de);
- return treat_one_path(dir, path, len, simplify, dtype, de);
-}
-
/*
* Read a directory tree. We currently ignore anything but
* directories, regular files and symlinks. That's because git
@@ -962,40 +1034,46 @@ static enum path_treatment treat_path(struct dir_struct *dir,
* That likely will not change.
*/
static int read_directory_recursive(struct dir_struct *dir,
- const char *base, int baselen,
+ struct strbuf *base,
int check_only,
- const struct path_simplify *simplify)
+ enum interesting match)
{
- DIR *fdir = opendir(*base ? base : ".");
- int contents = 0;
- struct dirent *de;
- char path[PATH_MAX + 1];
+ unsigned long size;
+ void *tree_buf = dir_to_tree(base, &size);
+ int contents = 0, baselen = base->len;
+ struct tree_desc desc;
+ struct name_entry ne;
- if (!fdir)
+ if (!tree_buf)
return 0;
- memcpy(path, base, baselen);
+ init_tree_desc(&desc, tree_buf, size);
- while ((de = readdir(fdir)) != NULL) {
- int len;
- switch (treat_path(dir, de, path, sizeof(path),
- baselen, simplify, &len)) {
+ while (tree_entry(&desc, &ne)) {
+ strbuf_setlen(base, baselen);
+ if (match != all_entries_interesting) {
+ match = match_both_pathspecs(dir, base, &ne);
+ if (match == all_entries_not_interesting)
+ break;
+ if (match == entry_not_interesting)
+ continue;
+ }
+ switch (treat_path(dir, base, &ne, match)) {
case path_recurse:
- contents += read_directory_recursive(dir, path, len, 0, simplify);
- continue;
- case path_ignored:
+ contents += read_directory_recursive(dir, base, 0, match);
continue;
case path_handled:
+ contents++;
+ if (check_only)
+ goto exit_early;
+
+ dir_add_name(dir, base->buf, base->len);
break;
}
- contents++;
- if (check_only)
- goto exit_early;
- else
- dir_add_name(dir, path, len);
}
exit_early:
- closedir(fdir);
+ free(tree_buf);
+ strbuf_setlen(base, baselen);
return contents;
}
@@ -1054,6 +1132,7 @@ static void free_simplify(struct path_simplify *simplify)
free(simplify);
}
+#if 0
static int treat_leading_path(struct dir_struct *dir,
const char *path, int len,
const struct path_simplify *simplify)
@@ -1088,20 +1167,52 @@ static int treat_leading_path(struct dir_struct *dir,
return 1; /* finished checking */
}
}
+#endif
-int read_directory(struct dir_struct *dir, const char *path, int len, const char **pathspec)
+int read_directory(struct dir_struct *dir, const char *path, int len,
+ const char **pathspec)
{
- struct path_simplify *simplify;
+ char *newpath = NULL;
+ struct strbuf base = STRBUF_INIT;
if (has_symlink_leading_path(path, len))
return dir->nr;
- simplify = create_simplify(pathspec);
- if (!len || treat_leading_path(dir, path, len, simplify))
- read_directory_recursive(dir, path, len, 0, simplify);
- free_simplify(simplify);
+ /*
+ * tree_entry_interesting() does not implement AND operator on
+ * pathspecs so we call tree_entry_interesting() twice and
+ * join the results ourselves in match_both_pathspecs()
+ */
+ if (path && *path) {
+ const char *pathspec1[2];
+ newpath = xmalloc(len + 1);
+ memcpy(newpath, path, len);
+ newpath[len] = 0;
+ pathspec1[0] = newpath;
+ pathspec1[1] = NULL;
+ init_pathspec(&dir->ps1, pathspec1);
+ }
+ else
+ init_pathspec(&dir->ps1, NULL);
+ init_pathspec(&dir->ps2, pathspec);
+
+ if (dir->flags & DIR_COLLECT_IGNORED) {
+ int size = sizeof(*dir->useful) * dir->ps2.nr;
+ dir->useful = xmalloc(size);
+ /* guilty until proven useful */
+ memset(dir->useful, 0, size);
+ }
+
+ read_directory_recursive(dir, &base, 0, entry_not_interesting);
+
+ strbuf_release(&base);
+ free_pathspec(&dir->ps1);
+ if (!(dir->flags & DIR_COLLECT_IGNORED))
+ free_pathspec(&dir->ps2);
+ free(newpath);
+
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
- qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name);
+
return dir->nr;
}
diff --git a/dir.h b/dir.h
index dd6947e..362d7b1 100644
--- a/dir.h
+++ b/dir.h
@@ -43,6 +43,11 @@ struct dir_struct {
} flags;
struct dir_entry **entries;
struct dir_entry **ignored;
+ int *useful;
+
+ /* Include info (a joint of ps1 and ps2) */
+ struct pathspec ps1;
+ struct pathspec ps2;
/* Exclude info */
const char *exclude_per_dir;
diff --git a/tree-walk.c b/tree-walk.c
index 6e12f0f..b56fec1 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -600,6 +600,8 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
const char *base_str = base->buf + base_offset;
int matchlen = item->len;
+ /* TODO: 07ccbff (runstatus: do not recurse into subdirectories if not needed - 2006-09-28) */
+
/* assume it will be used (which usually means break
the loop and return), reset it otherwise */
item->useful = 1;
--
1.7.3.1.256.g2539c.dirty
^ permalink raw reply related
* [PATCH/WIP 09/11] tree_entry_interesting: differentiate partial vs full match
From: Nguyễn Thái Ngọc Duy @ 2011-10-24 6:36 UTC (permalink / raw)
To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1319438176-7304-1-git-send-email-pclouds@gmail.com>
Up until now, for a/b pathspec, both paths a and a/b would return
entry_interesting. Make it return entry_matched for the latter.
This way if the caller follows up to "a", but decide to stop for some
reason, then it knows that "a" has not really matched the given
pathspec yet.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
tree-walk.c | 13 ++++++++-----
tree-walk.h | 5 +++--
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/tree-walk.c b/tree-walk.c
index 5e9c522..6e12f0f 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -616,19 +616,22 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
baselen - matchlen - 1,
!!S_ISDIR(entry->mode),
ps->max_depth) ?
- entry_interesting : entry_not_interesting;
+ entry_matched : entry_not_interesting;
}
/* Either there must be no base, or the base must match. */
if (baselen == 0 || !strncmp(base_str, match, baselen)) {
if (match_entry(entry, pathlen,
match + baselen, matchlen - baselen,
- &never_interesting))
- return entry_interesting;
+ &never_interesting)) {
+ if (match[baselen + pathlen] == '/')
+ return entry_interesting;
+ return entry_matched;
+ }
if (item->use_wildcard) {
if (!fnmatch(match + baselen, entry->path, 0))
- return entry_interesting;
+ return entry_matched;
/*
* Match all directories. We'll try to
@@ -654,7 +657,7 @@ match_wildcards:
if (!fnmatch(match, base->buf + base_offset, 0)) {
strbuf_setlen(base, base_offset + baselen);
- return entry_interesting;
+ return entry_matched;
}
strbuf_setlen(base, base_offset + baselen);
diff --git a/tree-walk.h b/tree-walk.h
index 2bf0db9..a5f92fa 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -65,8 +65,9 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru
enum interesting {
all_entries_not_interesting = -1, /* no, and no subsequent entries will be either */
entry_not_interesting = 0,
- entry_interesting = 1,
- all_entries_interesting = 2 /* yes, and all subsequent entries will be */
+ entry_interesting = 1, /* a potential match, not not there yet */
+ entry_matched = 2,
+ all_entries_interesting = 3 /* yes, and all subsequent entries will be */
};
extern enum interesting tree_entry_interesting(const struct name_entry *,
--
1.7.3.1.256.g2539c.dirty
^ permalink raw reply related
* [PATCH/WIP 08/11] tree-walk: mark useful pathspecs
From: Nguyễn Thái Ngọc Duy @ 2011-10-24 6:36 UTC (permalink / raw)
To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1319438176-7304-1-git-send-email-pclouds@gmail.com>
Useful pathspecs are those that help decide whether an item is in or
out, as opposed to useless ones whose existence does not change the
results.
Callers are responsible for cleaning before use, or doing anything
after.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
cache.h | 1 +
tree-walk.c | 13 ++++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/cache.h b/cache.h
index be07ec7..946d910 100644
--- a/cache.h
+++ b/cache.h
@@ -532,6 +532,7 @@ struct pathspec {
const char *match;
int len;
unsigned int use_wildcard:1;
+ unsigned int useful:1;
} *items;
};
diff --git a/tree-walk.c b/tree-walk.c
index 2d9d17a..5e9c522 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -595,11 +595,15 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
pathlen = tree_entry_len(entry);
for (i = ps->nr - 1; i >= 0; i--) {
- const struct pathspec_item *item = ps->items+i;
+ struct pathspec_item *item = ps->items+i;
const char *match = item->match;
const char *base_str = base->buf + base_offset;
int matchlen = item->len;
+ /* assume it will be used (which usually means break
+ the loop and return), reset it otherwise */
+ item->useful = 1;
+
if (baselen >= matchlen) {
/* If it doesn't match, move along... */
if (!match_dir_prefix(base_str, match, matchlen))
@@ -634,12 +638,12 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
return entry_interesting;
}
- continue;
+ goto nouse;
}
match_wildcards:
if (!item->use_wildcard)
- continue;
+ goto nouse;
/*
* Concatenate base and entry->path into one and do
@@ -660,6 +664,9 @@ match_wildcards:
*/
if (ps->recursive && S_ISDIR(entry->mode))
return entry_interesting;
+
+nouse:
+ item->useful = 0;
}
return never_interesting; /* No matches */
}
--
1.7.3.1.256.g2539c.dirty
^ permalink raw reply related
* [PATCH/WIP 07/11] tree_entry_interesting: make use of local pointer "item"
From: Nguyễn Thái Ngọc Duy @ 2011-10-24 6:36 UTC (permalink / raw)
To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1319438176-7304-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
tree-walk.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tree-walk.c b/tree-walk.c
index fc03262..2d9d17a 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -622,7 +622,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
&never_interesting))
return entry_interesting;
- if (ps->items[i].use_wildcard) {
+ if (item->use_wildcard) {
if (!fnmatch(match + baselen, entry->path, 0))
return entry_interesting;
@@ -638,7 +638,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
}
match_wildcards:
- if (!ps->items[i].use_wildcard)
+ if (!item->use_wildcard)
continue;
/*
--
1.7.3.1.256.g2539c.dirty
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox