Git development
 help / color / mirror / Atom feed
* Re: [NON-PATCH 3/2] Documentation/git-merge: format full commands in typewriter font
From: Jonathan Nieder @ 2010-01-07 20:25 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, Junio C Hamano
In-Reply-To: <ebbb4e2b0e98490a64b3cd52c33d3a995fa7e980.1262883414.git.trast@student.ethz.ch>

Thomas Rast wrote:

> * More importantly, while `code` style seems to be an improvement in
>   HTML output (because it gives typewriter font), my local 'man'
>   renders 'emphasis' as underlines -- which actually makes the code
>   snippets much more visible than `literal` quotes which are not
>   rendered specially at all.

Maybe some point in the asciidoc/docbook-xsl/nroff chain could be
convinced to render `literal` quotes underlined on the console.

Jonathan

^ permalink raw reply

* Re: [NON-PATCH 3/2] Documentation/git-merge: format full commands in typewriter font
From: Junio C Hamano @ 2010-01-07 21:08 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git
In-Reply-To: <ebbb4e2b0e98490a64b3cd52c33d3a995fa7e980.1262883414.git.trast@student.ethz.ch>

Thomas Rast <trast@student.ethz.ch> writes:

> * More importantly, while `code` style seems to be an improvement in
>   HTML output (because it gives typewriter font), my local 'man'
>   renders 'emphasis' as underlines -- which actually makes the code
>   snippets much more visible than `literal` quotes which are not
>   rendered specially at all.
>
> So which way should it be changed?

I'd prefer to see us mark code as `code`.

The documentation toolchain may hopefully be fixed in the upstream in the
future, and we could keep our local style tweaks in Documentation/ until
that happens if we really wanted to.

^ permalink raw reply

* Re: [PATCH (v2) 2/2] rebase -i: teach --onto A...B syntax
From: Johannes Sixt @ 2010-01-07 21:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nanako Shiraishi, Johannes Schindelin, git
In-Reply-To: <7vtyux3bx1.fsf@alter.siamese.dyndns.org>

On Donnerstag, 7. Januar 2010, Junio C Hamano wrote:
> I was tempted to suggest having a common helper function, 
> but as Dscho mentioned "rebase -i" implementation does not share much with
> "rebase" (even though it shares the external command line interface from
> the end user's point of view), and I don't see a readily available place
> (other than in git-sh-setup) to do so.
>
> Ideas?

1. Split git-rebase--merge.sh and git-rebase--am.sh backends off of 
git-rebase.sh. Have git-rebase.sh dispatch to 
git-rebase--{am,merge,interactive}.sh as appropriate.

2. Unify command line parsing from git-rebase--*.sh in git-rebase.sh. The 
git-rebase--*.sh can now simply refer to shell variables that were set by 
command line switches (the backends must be invoked using the . (dot) 
command).

3. Place common functionality like the one above in git-rebase.sh.

-- Hannes

^ permalink raw reply

* git-log - hide parent (was: merging two equivalent branches)
From: David Reitter @ 2010-01-07 21:16 UTC (permalink / raw)
  To: git, Christian MICHON
In-Reply-To: <46d6db661001071022t79ca65foac249d948a20c328@mail.gmail.com>

On Jan 7, 2010, at 1:22 PM, Christian MICHON wrote:
> I recall asking a similar question in 2008, and the answer was to look
> at "git graft" and use "git filter-branch" to recreate history.

Thanks, I've tried that and I recall that filter-branch wasn't willing to rewrite just the recent history - at least in started going over all 100k revisions at a very slow pace.  

I'm still unsure how, after the filter-branch, I would have some ancestor from the B series so that future pulls from the remote work, while having an ancestor from A, to make sure I can continue merging into C.  If history is rewritten, I'll get new revisions and lose ancestors.  
I'm beginning to thing that the cutting and pasting I'd like is conceptually impossible.

So what one would need is to specify a "silent parent" for a revision that is relevant w.r.t. future three-way merges, but indicates that the history behind the silent parent is irrelevant and shouldn't be shown in a git-log.  The runaway parent would be guaranteed to _not_ contribute any content to the tree of the child revision, as is the case with a "merge ours".

This could be implemented as a way to mark a parent as silent (checked by git-log at least), but one could also allow for an empty commit that, while having a normal parent, clears out the tree. 

Let me know if this idea is completely crazy. 

^ permalink raw reply

* [PATCH] mingw: enable NO_PYTHON
From: Erik Faye-Lund @ 2010-01-07 21:52 UTC (permalink / raw)
  To: msysgit; +Cc: git, Erik Faye-Lund

Python is not commonly installed on Windows machines, so
we should disable it there by default.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---

This patch is against Junio's current master, and enables
msysgit to compile upstream git again after Sverre's addition
of the python remote-helpers (2fe40b6).

 Makefile |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile
index 1c7668a..a2780a2 100644
--- a/Makefile
+++ b/Makefile
@@ -1028,6 +1028,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	BLK_SHA1 = YesPlease
 	NO_INET_PTON = YesPlease
 	NO_INET_NTOP = YesPlease
+	NO_PYTHON = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
-- 
1.6.6.95.g82b1b.dirty

^ permalink raw reply related

* [PATCH 0/5] Miscellaneous improvements on Windows
From: Johannes Sixt @ 2010-01-07 21:54 UTC (permalink / raw)
  To: msysgit; +Cc: git, Johannes Sixt

This series is actually a set of independent changes that improve
the Windows port. (Except that 2/5 depends on 1/5.)

1/5 and 2/5 enable threaded code on Windows. This topic was discussed
beginning of November. The change to builtin-pack-objects.c was
positively commented (though not formally acked) by Nico:

http://thread.gmane.org/gmane.comp.version-control.git/131998/focus=132239

3/5 removes a static dependency on shell32.dll so that startup time is
reduced. It does reduce the runtime of the test suite ('make -j2 test')
from 16:00min to 12:40min for me.

4/5 (the new pipe implementation) could be considered code churn.
It reduces LOC, but the effect is not noticable during run-time.

5/5 (avoid "dup dance") straightens our run-command implementation a
bit. It is more of the future-proofing kind because it avoids that a
writable pipe end remains accidentally open in a child process, leaving
the reader waiting idenfinetly. This doesn't seem to be a problem
currently, though.


I'm using these patches since November.


Andrzej K. Haczewski (1):
  MSVC: Windows-native implementation for subset of Pthreads API

Johannes Sixt (4):
  MinGW: enable pthreads
  Windows: boost startup by avoiding a static dependency on shell32.dll
  Windows: simplify the pipe(2) implementation
  Windows: avoid the "dup dance" when spawning a child process

 Makefile               |   13 +++--
 builtin-pack-objects.c |   31 +++++++++++--
 compat/mingw.c         |   80 ++++++++++++++++----------------
 compat/mingw.h         |    8 +++-
 compat/win32/pthread.c |  120 ++++++++++++++++++++++++++++++++++++++++++++++++
 compat/win32/pthread.h |   68 +++++++++++++++++++++++++++
 run-command.c          |   71 ++++++++++++----------------
 7 files changed, 300 insertions(+), 91 deletions(-)
 create mode 100644 compat/win32/pthread.c
 create mode 100644 compat/win32/pthread.h

^ permalink raw reply

* [PATCH 1/5] MSVC: Windows-native implementation for subset of Pthreads API
From: Johannes Sixt @ 2010-01-07 21:54 UTC (permalink / raw)
  To: msysgit; +Cc: git, Andrzej K. Haczewski, Johannes Sixt
In-Reply-To: <cover.1262895936.git.j6t@kdbg.org>

From: Andrzej K. Haczewski <ahaczewski@gmail.com>

This patch implements native to Windows subset of pthreads API used by Git.
It allows to remove Pthreads for Win32 dependency for MSVC, msysgit and
Cygwin.

The patch modifies Makefile only for MSVC (that's the environment I'm
capable of testing on), so it requires further corrections to compile
with MinGW or Cygwin.

Signed-off-by: Andrzej K. Haczewski <ahaczewski@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 Makefile               |    7 ++-
 builtin-pack-objects.c |   31 +++++++++++--
 compat/mingw.c         |    2 +-
 compat/mingw.h         |    5 ++
 compat/win32/pthread.c |  120 ++++++++++++++++++++++++++++++++++++++++++++++++
 compat/win32/pthread.h |   68 +++++++++++++++++++++++++++
 6 files changed, 225 insertions(+), 8 deletions(-)
 create mode 100644 compat/win32/pthread.c
 create mode 100644 compat/win32/pthread.h

diff --git a/Makefile b/Makefile
index 4a1e5bc..ed547d9 100644
--- a/Makefile
+++ b/Makefile
@@ -451,6 +451,7 @@ LIB_H += commit.h
 LIB_H += compat/bswap.h
 LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
+LIB_H += compat/win32/pthread.h
 LIB_H += csum-file.h
 LIB_H += decorate.h
 LIB_H += delta.h
@@ -967,15 +968,15 @@ ifeq ($(uname_S),Windows)
 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 	NO_REGEX = YesPlease
 	NO_CURL = YesPlease
-	NO_PTHREADS = YesPlease
+	THREADED_DELTA_SEARCH = YesPlease
 	BLK_SHA1 = YesPlease
 
 	CC = compat/vcbuild/scripts/clink.pl
 	AR = compat/vcbuild/scripts/lib.pl
 	CFLAGS =
 	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/fnmatch/fnmatch.o compat/winansi.o
-	COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -DSTRIP_EXTENSION=\".exe\"
+	COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o
+	COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
 	BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
 	EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib
 	lib =
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 4429d53..2fdabaa 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -1256,15 +1256,15 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
 
 #ifdef THREADED_DELTA_SEARCH
 
-static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t read_mutex;
 #define read_lock()		pthread_mutex_lock(&read_mutex)
 #define read_unlock()		pthread_mutex_unlock(&read_mutex)
 
-static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t cache_mutex;
 #define cache_lock()		pthread_mutex_lock(&cache_mutex)
 #define cache_unlock()		pthread_mutex_unlock(&cache_mutex)
 
-static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t progress_mutex;
 #define progress_lock()		pthread_mutex_lock(&progress_mutex)
 #define progress_unlock()	pthread_mutex_unlock(&progress_mutex)
 
@@ -1591,7 +1591,26 @@ struct thread_params {
 	unsigned *processed;
 };
 
-static pthread_cond_t progress_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t progress_cond;
+
+/*
+ * Mutex and conditional variable can't be statically-initialized on Windows.
+ */
+static void init_threaded_search()
+{
+	pthread_mutex_init(&read_mutex, NULL);
+	pthread_mutex_init(&cache_mutex, NULL);
+	pthread_mutex_init(&progress_mutex, NULL);
+	pthread_cond_init(&progress_cond, NULL);
+}
+
+static void cleanup_threaded_search()
+{
+	pthread_cond_destroy(&progress_cond);
+	pthread_mutex_destroy(&read_mutex);
+	pthread_mutex_destroy(&cache_mutex);
+	pthread_mutex_destroy(&progress_mutex);
+}
 
 static void *threaded_find_deltas(void *arg)
 {
@@ -1630,10 +1649,13 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
 	struct thread_params *p;
 	int i, ret, active_threads = 0;
 
+	init_threaded_search();
+
 	if (!delta_search_threads)	/* --threads=0 means autodetect */
 		delta_search_threads = online_cpus();
 	if (delta_search_threads <= 1) {
 		find_deltas(list, &list_size, window, depth, processed);
+		cleanup_threaded_search();
 		return;
 	}
 	if (progress > pack_to_stdout)
@@ -1748,6 +1770,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
 			active_threads--;
 		}
 	}
+	cleanup_threaded_search();
 	free(p);
 }
 
diff --git a/compat/mingw.c b/compat/mingw.c
index 0d73f15..bc3dc74 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -5,7 +5,7 @@
 
 #include <shellapi.h>
 
-static int err_win_to_posix(DWORD winerr)
+int err_win_to_posix(DWORD winerr)
 {
 	int error = ENOSYS;
 	switch(winerr) {
diff --git a/compat/mingw.h b/compat/mingw.h
index b3d299f..e681135 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -307,3 +307,8 @@ struct mingw_dirent
 #define readdir(x) mingw_readdir(x)
 struct dirent *mingw_readdir(DIR *dir);
 #endif // !NO_MINGW_REPLACE_READDIR
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+extern int err_win_to_posix(DWORD winerr);
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
new file mode 100644
index 0000000..652d7b4
--- /dev/null
+++ b/compat/win32/pthread.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
+ *
+ * DISCLAMER: The implementation is Git-specific, it is subset of original
+ * Pthreads API, without lots of other features that Git doesn't use.
+ * Git also makes sure that the passed arguments are valid, so there's
+ * no need for double-checking.
+ */
+
+#include "../../git-compat-util.h"
+#include "pthread.h"
+
+#include <errno.h>
+#include <limits.h>
+
+static unsigned __stdcall win32_start_routine(void *arg)
+{
+	pthread_t *thread = arg;
+	thread->arg = thread->start_routine(thread->arg);
+	return 0;
+}
+
+int pthread_create(pthread_t *thread, const void *unused,
+		   void *(*start_routine)(void*), void *arg)
+{
+	thread->arg = arg;
+	thread->start_routine = start_routine;
+	thread->handle = (HANDLE)
+		_beginthreadex(NULL, 0, win32_start_routine, thread, 0, NULL);
+
+	if (!thread->handle)
+		return errno;
+	else
+		return 0;
+}
+
+int win32_pthread_join(pthread_t *thread, void **value_ptr)
+{
+	DWORD result = WaitForSingleObject(thread->handle, INFINITE);
+	switch (result) {
+		case WAIT_OBJECT_0:
+			if (value_ptr)
+				*value_ptr = thread->arg;
+			return 0;
+		case WAIT_ABANDONED:
+			return EINVAL;
+		default:
+			return err_win_to_posix(GetLastError());
+	}
+}
+
+int pthread_cond_init(pthread_cond_t *cond, const void *unused)
+{
+	cond->waiters = 0;
+
+	InitializeCriticalSection(&cond->waiters_lock);
+
+	cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+	if (!cond->sema)
+		die("CreateSemaphore() failed");
+	return 0;
+}
+
+int pthread_cond_destroy(pthread_cond_t *cond)
+{
+	CloseHandle(cond->sema);
+	cond->sema = NULL;
+
+	DeleteCriticalSection(&cond->waiters_lock);
+
+	return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
+{
+	/* serialize access to waiters count */
+	EnterCriticalSection(&cond->waiters_lock);
+	++cond->waiters;
+	LeaveCriticalSection(&cond->waiters_lock);
+
+	/*
+	 * Unlock external mutex and wait for signal.
+	 * NOTE: we've held mutex locked long enough to increment
+	 * waiters count above, so there's no problem with
+	 * leaving mutex unlocked before we wait on semaphore.
+	 */
+	LeaveCriticalSection(mutex);
+
+	/* let's wait - ignore return value */
+	WaitForSingleObject(cond->sema, INFINITE);
+
+	/* we're done waiting, so make sure we decrease waiters count */
+	EnterCriticalSection(&cond->waiters_lock);
+	--cond->waiters;
+	LeaveCriticalSection(&cond->waiters_lock);
+
+	/* lock external mutex again */
+	EnterCriticalSection(mutex);
+
+	return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t *cond)
+{
+	int have_waiters;
+
+	/* serialize access to waiters count */
+	EnterCriticalSection(&cond->waiters_lock);
+	have_waiters = cond->waiters > 0;
+	LeaveCriticalSection(&cond->waiters_lock);
+
+	/*
+	 * Signal only when there are waiters
+	 */
+	if (have_waiters)
+		return ReleaseSemaphore(cond->sema, 1, NULL) ?
+			0 : err_win_to_posix(GetLastError());
+	else
+		return 0;
+}
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
new file mode 100644
index 0000000..47888e4
--- /dev/null
+++ b/compat/win32/pthread.h
@@ -0,0 +1,68 @@
+/*
+ * Header used to adapt pthread-based POSIX code to Windows API threads.
+ *
+ * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
+ */
+
+#ifndef PTHREAD_H
+#define PTHREAD_H
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+/*
+ * Defines that adapt Windows API threads to pthreads API
+ */
+#define pthread_mutex_t CRITICAL_SECTION
+
+#define pthread_mutex_init(a,b) InitializeCriticalSection((a))
+#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
+#define pthread_mutex_lock EnterCriticalSection
+#define pthread_mutex_unlock LeaveCriticalSection
+
+/*
+ * Implement simple condition variable for Windows threads, based on ACE
+ * implementation.
+ *
+ * See original implementation: http://bit.ly/1vkDjo
+ * ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html
+ * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
+ */
+typedef struct {
+	LONG waiters;
+	CRITICAL_SECTION waiters_lock;
+	HANDLE sema;
+} pthread_cond_t;
+
+extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
+
+extern int pthread_cond_destroy(pthread_cond_t *cond);
+
+extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
+
+extern int pthread_cond_signal(pthread_cond_t *cond);
+
+/*
+ * Simple thread creation implementation using pthread API
+ */
+typedef struct {
+	HANDLE handle;
+	void *(*start_routine)(void*);
+	void *arg;
+} pthread_t;
+
+extern int pthread_create(pthread_t *thread, const void *unused,
+			  void *(*start_routine)(void*), void *arg);
+
+/*
+ * To avoid the need of copying a struct, we use small macro wrapper to pass
+ * pointer to win32_pthread_join instead.
+ */
+#define pthread_join(a, b) win32_pthread_join(&(a), (b))
+
+extern int win32_pthread_join(pthread_t *thread, void **value_ptr);
+
+#endif /* PTHREAD_H */
-- 
1.6.6.115.gd1ab3

^ permalink raw reply related

* [PATCH 2/5] MinGW: enable pthreads
From: Johannes Sixt @ 2010-01-07 21:54 UTC (permalink / raw)
  To: msysgit; +Cc: git, Johannes Sixt
In-Reply-To: <cover.1262895936.git.j6t@kdbg.org>

If the MinGW build was built as part of the msysgit build environment,
then threading was already enabled because the pthreads-win32 package
is available in msysgit.

The previous patch added a minimal pthreads implementation for Windows.
Therefore, we can now enable code that uses pthreads unconditionally.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 Makefile |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index ed547d9..087c3fa 100644
--- a/Makefile
+++ b/Makefile
@@ -1019,9 +1019,11 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 	NO_REGEX = YesPlease
 	BLK_SHA1 = YesPlease
+	THREADED_DELTA_SEARCH = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
-	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
+	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
+		compat/win32/pthread.o
 	EXTLIBS += -lws2_32
 	X = .exe
 ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
@@ -1031,10 +1033,8 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
 	EXTLIBS += /mingw/lib/libz.a
 	NO_R_TO_GCC_LINKER = YesPlease
 	INTERNAL_QSORT = YesPlease
-	THREADED_DELTA_SEARCH = YesPlease
 else
 	NO_CURL = YesPlease
-	NO_PTHREADS = YesPlease
 endif
 endif
 
-- 
1.6.6.115.gd1ab3

^ permalink raw reply related

* [PATCH 3/5] Windows: boost startup by avoiding a static dependency on shell32.dll
From: Johannes Sixt @ 2010-01-07 21:54 UTC (permalink / raw)
  To: msysgit; +Cc: git, Johannes Sixt
In-Reply-To: <cover.1262895936.git.j6t@kdbg.org>

This DLL is only needed to invoke the browser in a "git help" call. By
looking up the only function that we need at runtime, we can avoid the
startup costs of this DLL.

DLL usage can be profiled with Microsoft's Dependency Walker. For example,
a call to "git diff-files" loaded

before:  19 DLLs
after:    9 DLLs

(The results depend on the OS; this is on Windows XP SP3.)

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 compat/mingw.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index bc3dc74..dfb1f05 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -3,8 +3,6 @@
 #include <conio.h>
 #include "../strbuf.h"
 
-#include <shellapi.h>
-
 int err_win_to_posix(DWORD winerr)
 {
 	int error = ENOSYS;
@@ -1338,8 +1336,22 @@ static const char *make_backslash_path(const char *path)
 void mingw_open_html(const char *unixpath)
 {
 	const char *htmlpath = make_backslash_path(unixpath);
+	typedef HINSTANCE (WINAPI *T)(HWND, const char *,
+			const char *, const char *, const char *, INT);
+	T ShellExecute;
+	HMODULE shell32;
+
+	shell32 = LoadLibrary("shell32.dll");
+	if (!shell32)
+		die("cannot load shell32.dll");
+	ShellExecute = (T)GetProcAddress(shell32, "ShellExecuteA");
+	if (!ShellExecute)
+		die("cannot run browser");
+
 	printf("Launching default browser to display HTML ...\n");
 	ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
+
+	FreeLibrary(shell32);
 }
 
 int link(const char *oldpath, const char *newpath)
-- 
1.6.6.115.gd1ab3

^ permalink raw reply related

* [PATCH 4/5] Windows: simplify the pipe(2) implementation
From: Johannes Sixt @ 2010-01-07 21:55 UTC (permalink / raw)
  To: msysgit; +Cc: git, Johannes Sixt
In-Reply-To: <cover.1262895936.git.j6t@kdbg.org>

Our implementation of pipe() must create non-inheritable handles for the
reason that when a child process is started, there is no opportunity to
close the unneeded pipe ends in the child (on POSIX this is done between
fork() and exec()).

Previously, we used the _pipe() function provided by Microsoft's C runtime
(which creates inheritable handles) and then turned the handles into
non-inheritable handles using the DuplicateHandle() API.

Simplify the procedure by using the CreatePipe() API, which can create
non-inheritable handles right from the beginning.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 compat/mingw.c |   37 ++++++++-----------------------------
 1 files changed, 8 insertions(+), 29 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index dfb1f05..9f4fab3 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -299,46 +299,25 @@ int gettimeofday(struct timeval *tv, void *tz)
 
 int pipe(int filedes[2])
 {
-	int fd;
-	HANDLE h[2], parent;
-
-	if (_pipe(filedes, 8192, 0) < 0)
-		return -1;
+	HANDLE h[2];
 
-	parent = GetCurrentProcess();
-
-	if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[0]),
-			parent, &h[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
-		close(filedes[0]);
-		close(filedes[1]);
-		return -1;
-	}
-	if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[1]),
-			parent, &h[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
-		close(filedes[0]);
-		close(filedes[1]);
-		CloseHandle(h[0]);
+	/* this creates non-inheritable handles */
+	if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
+		errno = err_win_to_posix(GetLastError());
 		return -1;
 	}
-	fd = _open_osfhandle((int)h[0], O_NOINHERIT);
-	if (fd < 0) {
-		close(filedes[0]);
-		close(filedes[1]);
+	filedes[0] = _open_osfhandle((int)h[0], O_NOINHERIT);
+	if (filedes[0] < 0) {
 		CloseHandle(h[0]);
 		CloseHandle(h[1]);
 		return -1;
 	}
-	close(filedes[0]);
-	filedes[0] = fd;
-	fd = _open_osfhandle((int)h[1], O_NOINHERIT);
-	if (fd < 0) {
+	filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT);
+	if (filedes[0] < 0) {
 		close(filedes[0]);
-		close(filedes[1]);
 		CloseHandle(h[1]);
 		return -1;
 	}
-	close(filedes[1]);
-	filedes[1] = fd;
 	return 0;
 }
 
-- 
1.6.6.115.gd1ab3

^ permalink raw reply related

* [PATCH 5/5] Windows: avoid the "dup dance" when spawning a  child process
From: Johannes Sixt @ 2010-01-07 21:55 UTC (permalink / raw)
  To: msysgit; +Cc: git, Johannes Sixt
In-Reply-To: <cover.1262895936.git.j6t@kdbg.org>

When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to

1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source

We used this idiom as well -- but we are not using the spawn() functions!

Instead, we have our own implementation (originally, because we have to
override the environment, too). We had hardcoded that stdin, stdout, and
stderr of the child process were inherited from the parent's fds 0, 1,
and 2. But we can actually specify any fd.

With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.

The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process.

Since our implementation of pipe() creates non-inheritable OS handles, we
still dup()s file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 compat/mingw.c |   25 +++++++++++++------
 compat/mingw.h |    3 +-
 run-command.c  |   71 ++++++++++++++++++++++++-------------------------------
 3 files changed, 50 insertions(+), 49 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 9f4fab3..74ffc18 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -615,8 +615,8 @@ static int env_compare(const void *a, const void *b)
 	return strcasecmp(*ea, *eb);
 }
 
-static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
-			   int prepend_cmd)
+static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
+			      int prepend_cmd, int fhin, int fhout, int fherr)
 {
 	STARTUPINFO si;
 	PROCESS_INFORMATION pi;
@@ -652,9 +652,9 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
 	memset(&si, 0, sizeof(si));
 	si.cb = sizeof(si);
 	si.dwFlags = STARTF_USESTDHANDLES;
-	si.hStdInput = (HANDLE) _get_osfhandle(0);
-	si.hStdOutput = (HANDLE) _get_osfhandle(1);
-	si.hStdError = (HANDLE) _get_osfhandle(2);
+	si.hStdInput = (HANDLE) _get_osfhandle(fhin);
+	si.hStdOutput = (HANDLE) _get_osfhandle(fhout);
+	si.hStdError = (HANDLE) _get_osfhandle(fherr);
 
 	/* concatenate argv, quoting args as we go */
 	strbuf_init(&args, 0);
@@ -709,7 +709,14 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
 	return (pid_t)pi.hProcess;
 }
 
-pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
+static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
+			   int prepend_cmd)
+{
+	return mingw_spawnve_fd(cmd, argv, env, prepend_cmd, 0, 1, 2);
+}
+
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
+		     int fhin, int fhout, int fherr)
 {
 	pid_t pid;
 	char **path = get_path_split();
@@ -731,13 +738,15 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
 				pid = -1;
 			}
 			else {
-				pid = mingw_spawnve(iprog, argv, env, 1);
+				pid = mingw_spawnve_fd(iprog, argv, env, 1,
+						       fhin, fhout, fherr);
 				free(iprog);
 			}
 			argv[0] = argv0;
 		}
 		else
-			pid = mingw_spawnve(prog, argv, env, 0);
+			pid = mingw_spawnve_fd(prog, argv, env, 0,
+					       fhin, fhout, fherr);
 		free(prog);
 	}
 	free_path_split(path);
diff --git a/compat/mingw.h b/compat/mingw.h
index e681135..238fd70 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -220,7 +220,8 @@ int mingw_fstat(int fd, struct stat *buf);
 int mingw_utime(const char *file_name, const struct utimbuf *times);
 #define utime mingw_utime
 
-pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
+		     int fhin, int fhout, int fherr);
 void mingw_execvp(const char *cmd, char *const *argv);
 #define execvp mingw_execvp
 
diff --git a/run-command.c b/run-command.c
index cf2d8f7..d270664 100644
--- a/run-command.c
+++ b/run-command.c
@@ -8,12 +8,14 @@ static inline void close_pair(int fd[2])
 	close(fd[1]);
 }
 
+#ifndef WIN32
 static inline void dup_devnull(int to)
 {
 	int fd = open("/dev/null", O_RDWR);
 	dup2(fd, to);
 	close(fd);
 }
+#endif
 
 int start_command(struct child_process *cmd)
 {
@@ -135,42 +137,30 @@ fail_pipe:
 			strerror(failed_errno = errno));
 #else
 {
-	int s0 = -1, s1 = -1, s2 = -1;	/* backups of stdin, stdout, stderr */
+	int fhin = 0, fhout = 1, fherr = 2;
 	const char **sargv = cmd->argv;
 	char **env = environ;
 
-	if (cmd->no_stdin) {
-		s0 = dup(0);
-		dup_devnull(0);
-	} else if (need_in) {
-		s0 = dup(0);
-		dup2(fdin[0], 0);
-	} else if (cmd->in) {
-		s0 = dup(0);
-		dup2(cmd->in, 0);
-	}
-
-	if (cmd->no_stderr) {
-		s2 = dup(2);
-		dup_devnull(2);
-	} else if (need_err) {
-		s2 = dup(2);
-		dup2(fderr[1], 2);
-	}
-
-	if (cmd->no_stdout) {
-		s1 = dup(1);
-		dup_devnull(1);
-	} else if (cmd->stdout_to_stderr) {
-		s1 = dup(1);
-		dup2(2, 1);
-	} else if (need_out) {
-		s1 = dup(1);
-		dup2(fdout[1], 1);
-	} else if (cmd->out > 1) {
-		s1 = dup(1);
-		dup2(cmd->out, 1);
-	}
+	if (cmd->no_stdin)
+		fhin = open("/dev/null", O_RDWR);
+	else if (need_in)
+		fhin = dup(fdin[0]);
+	else if (cmd->in)
+		fhin = dup(cmd->in);
+
+	if (cmd->no_stderr)
+		fherr = open("/dev/null", O_RDWR);
+	else if (need_err)
+		fherr = dup(fderr[1]);
+
+	if (cmd->no_stdout)
+		fhout = open("/dev/null", O_RDWR);
+	else if (cmd->stdout_to_stderr)
+		fhout = dup(fherr);
+	else if (need_out)
+		fhout = dup(fdout[1]);
+	else if (cmd->out > 1)
+		fhout = dup(cmd->out);
 
 	if (cmd->dir)
 		die("chdir in start_command() not implemented");
@@ -181,7 +171,8 @@ fail_pipe:
 		cmd->argv = prepare_git_cmd(cmd->argv);
 	}
 
-	cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
+	cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env,
+				  fhin, fhout, fherr);
 	failed_errno = errno;
 	if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
 		error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
@@ -192,12 +183,12 @@ fail_pipe:
 		free(cmd->argv);
 
 	cmd->argv = sargv;
-	if (s0 >= 0)
-		dup2(s0, 0), close(s0);
-	if (s1 >= 0)
-		dup2(s1, 1), close(s1);
-	if (s2 >= 0)
-		dup2(s2, 2), close(s2);
+	if (fhin != 0)
+		close(fhin);
+	if (fhout != 1)
+		close(fhout);
+	if (fherr != 2)
+		close(fherr);
 }
 #endif
 
-- 
1.6.6.115.gd1ab3

^ permalink raw reply related

* Re: [PATCH] mingw: enable NO_PYTHON
From: Erik Faye-Lund @ 2010-01-07 22:00 UTC (permalink / raw)
  To: msysgit; +Cc: git, Erik Faye-Lund
In-Reply-To: <1262901159-1436-1-git-send-email-kusmabite@gmail.com>

Uhm, I just realized that I sent out a patch that wasn't clean against
Junio's master after all. I'll send out a fixed one ASAP.

Sorry about the noise.

On Thu, Jan 7, 2010 at 10:52 PM, Erik Faye-Lund
<kusmabite@googlemail.com> wrote:
> Python is not commonly installed on Windows machines, so
> we should disable it there by default.
>
> Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
> ---
>
> This patch is against Junio's current master, and enables
> msysgit to compile upstream git again after Sverre's addition
> of the python remote-helpers (2fe40b6).
>
>  Makefile |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 1c7668a..a2780a2 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1028,6 +1028,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
>        BLK_SHA1 = YesPlease
>        NO_INET_PTON = YesPlease
>        NO_INET_NTOP = YesPlease
> +       NO_PYTHON = YesPlease
>        COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
>        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
>        COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
> --
> 1.6.6.95.g82b1b.dirty
>
>



-- 
Erik "kusma" Faye-Lund

^ permalink raw reply

* [PATCH] mingw: disable Python
From: Erik Faye-Lund @ 2010-01-07 22:07 UTC (permalink / raw)
  To: msysgit; +Cc: git, Erik Faye-Lund
In-Reply-To: <40aa078e1001071400j21900ed1n415394491d469b8c@mail.gmail.com>

Python is not commonly installed on Windows machines, so
we should disable it there by default.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---

This patch is against Junio's current master, and enables
msysgit to compile upstream git again after Sverre's addition
of the python remote-helpers (2fe40b6).

 Makefile |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile
index 015bfab..0004c52 100644
--- a/Makefile
+++ b/Makefile
@@ -1027,6 +1027,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 	NO_REGEX = YesPlease
 	BLK_SHA1 = YesPlease
+	NO_PYTHON = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
-- 
1.6.6.90.g50bc9.dirty

^ permalink raw reply related

* [PATCH] Documentation: pack-objects: Clarify --local's semantics.
From: Nelson Elhage @ 2010-01-07 22:10 UTC (permalink / raw)
  To: git, gitster; +Cc: Nelson Elhage

The current documentation suggests that --local also ignores any
objects in local packs, which is incorrect. Change the language to be
clearer and more parallel to the other options that ignore objects.

While we're at it, fix a trivial error in --incremental's
documentation.

Signed-off-by: Nelson Elhage <nelhage@mit.edu>
---
 Documentation/git-pack-objects.txt |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index f54d433..d8e5686 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -117,14 +117,13 @@ base-name::
 	standard input.
 
 --incremental::
-	This flag causes an object already in a pack ignored
+	This flag causes an object already in a pack to be ignored
 	even if it appears in the standard input.
 
 --local::
-	This flag is similar to `--incremental`; instead of
-	ignoring all packed objects, it only ignores objects
-	that are packed and/or not in the local object store
-	(i.e. borrowed from an alternate).
+	This flag causes an object that is borrowed from an alternate
+	object store to be ignored even if it appears in the standard
+	input.
 
 --non-empty::
         Only create a packed archive if it would contain at
-- 
1.6.5.40.g402af7

^ permalink raw reply related

* Re: Difference between pull --rebase and fetch+rebase
From: Santi Béjar @ 2010-01-07 22:33 UTC (permalink / raw)
  To: martinvz; +Cc: git
In-Reply-To: <1262889864880-4268064.post@n2.nabble.com>

[Do not top post, as it breaks the conversation flow]

On Thu, Jan 7, 2010 at 7:44 PM, martinvz
<martin.von.zweigbergk@gmail.com> wrote:
>
> Thanks for your post, Santi. I can not share my repository since it is a
> project at work. I was troubleshooting a bit myself and found the following
> section in git-pull.sh:
>
>        oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
>        for reflog in $(git rev-list -g $remoteref 2>/dev/null)
>        do
>                if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
>                then
>                        oldremoteref="$reflog"
>                        break
>                fi
>        done
>
> Why is it that reflog entries are allowed to override the remote reference?

This is used when the upstream branch is rebased, as you only want to
rebase the local commits and not commits in the old upstream branch.

Is your upstream branch rebased?

Can you provide, at least, a graph of your history (ala git log
--graph --oneline for example)? And plot also the reflog entries and
all the important commits.

Santi

^ permalink raw reply

* Problem Using Git with Subversion Repository
From: Bryan Richardson @ 2010-01-07 22:53 UTC (permalink / raw)
  To: git

Hello all,

Has anyone come across a similar problem as this?

Item already exists in filesystem: File already exists: filesystem
'/usr/local/svn/repos/my-apps/db', transaction '96-2v', path
'/app/trunk/vendor/rails/actionpack/test/fixtures/layout_tests/layouts/symlinked'
at /usr/lib/git-core/git-svn line 508

I *think* what happened is in a previous git-svn dcommit I removed the
vendor/rails directory (unfroze rails from my app) and now I'm trying
to freeze it again, in which case git-svn thinks a file needs to be
added (instead of modified) and the Subversion repository says the
file already exists.

Anyone know a way around it?!

--
Thanks!
Bryan

^ permalink raw reply

* Re: Difference between pull --rebase and fetch+rebase
From: martinvz @ 2010-01-07 23:38 UTC (permalink / raw)
  To: git
In-Reply-To: <adf1fd3d1001071433j6cd36641sdd2dfd6a936d8483@mail.gmail.com>



Santi Béjar-2 wrote:
> 
> Is your upstream branch rebased?
> 

Sorry, but I'm not sure I understand what that means. Most of the commits in
the upstream branch (the remote main branch) were rebased onto that branch
at some point in time before being pushed to our shared repository. The
remote branch itself was never rebased against any other branch (all
destructive operations disallowed in Gitosis). I hope that (possibly along
with the information below) answers your question.


Santi Béjar-2 wrote:
> 
> Can you provide, at least, a graph of your history (ala git log
> --graph --oneline for example)? And plot also the reflog entries and
> all the important commits.
> 

$ git log --graph --format=%h --all
* 2038a46 # topic-2
* a7b93b2
* f2501ae # origin/main
* cd5aaa9
* cb232f3
...
* 5ed0d06
* 3067862
| * 6eba2fa # topic-1
| * b09aaf4
| * bc3b72a
|/
| * 03d0d84 # topic-3
| * 5160773
| * 3c25642
|/
| * 6e9b12b # topic-4
| * 75f5ab2
| * bdd08ce
| * b5d5759
|/
* 486b580
* a021696
* 3ffe7df
* d0f55c5
...

I have topic-1 checked out and run "git pull" and expect it to rebase (only)
commits bc3b72a, b09aaf4, 6eba2fa onto f2501ae, but it starts by applying
a021696 and 486b580.

$ git reflog -g origin/main
f2501ae refs/remotes/origin/mai\x7f\x7fn@{0}: fetch origin: fast forward
3ffe7df refs/remotes/origin/mai\x7f\x7fn@{1}: fetch origin: fast forward
...

I hope that's all that's all you need. It seems that the problem is that the
oldremoteref gets overwritten with the entry from the reflog. Is the problem
that 3ffe7df appears in the reflog or that 486b580 doesn't appear there? I'm
not clear on what ends up in the reflog.

I just realized that I myself created a021696 and 486b580 (but not 3ffe7df),
probably by rebasing some now-dead branch against origin/main.

Something else that may or may not have something to do with the problem is
that there is also a branch called origin/main-stable (pointing to the same
commit as origin/main). I also have a local main branch (also same commit as
origin/main). I don't know if any of this could confuse Git. (To be
perfectly honest, it is actually the origin/main-stable branch I'm trying to
pull from, just in case you think the branch name could have any impact.)


Thanks,
Martin

-- 
View this message in context: http://n2.nabble.com/Difference-between-pull-rebase-and-fetch-rebase-tp4266164p4269422.html
Sent from the git mailing list archive at Nabble.com.

^ permalink raw reply

* Re: origin/branchname and tracking branch pointing to different  commits?
From: Eugene Sajine @ 2010-01-07 23:50 UTC (permalink / raw)
  To: Thomas Rast, git; +Cc: Eugene Sajine
In-Reply-To: <76c5b8581001070925g21ac3136x2928f12dc43437e5@mail.gmail.com>

>
> Yep. That's what i though it is. I.e. origin/branchname will point
> always to the last pushed commit only. Isn't it a bit strange that git
> fetch doesn't update origin/qa?
>
> Probably the problem is that whenever I'm pulling or pushing to remote
> repo i expect the last updated state of particular remote branch to be
> reflected in origin/branchname, but IMHO it is correct expectation...
>
> What do you think?

let me correct my self a little bit:

$ git pull origin branchname

and

$git fetch origin branchname

are both causing the output like this:

>From git://....
* branch      branchname    -> FETCH_HEAD
...

but "git fetch" says:

>From git://....
* branch      branchname    -> origin/branchname

Is this inconsistent behavior necessary by design?

Thanks,
Eugene

^ permalink raw reply

* Re: origin/branchname and tracking branch pointing to different  commits?
From: Junio C Hamano @ 2010-01-08  0:32 UTC (permalink / raw)
  To: Eugene Sajine; +Cc: Thomas Rast, git
In-Reply-To: <76c5b8581001071550g31e9f5a3n15ebdb10a806ab2e@mail.gmail.com>

Eugene Sajine <euguess@gmail.com> writes:

> $ git fetch origin branchname
>
> are both causing the output like this:
>
> From git://....
> * branch      branchname    -> FETCH_HEAD
> ...
>
> but "git fetch" says:
>
> From git://....
> * branch      branchname    -> origin/branchname
>
> Is this inconsistent behavior necessary by design?

It is by design; it is debatable if it still makes sense, though.

Back when "git fetch" was invented, there weren't separate refs/remotes/
hierarchy, the distinction between what's local and what's remote were
only in user's head.  It made quite a lot of sense to have an explicit way
to prevent "fetch" from overwriting all the branches that track branches
from remote.  Suppose you have already spend considerable time inspecting
'origin/branch' and decided that has a suitable commit to build your
changes on, but you needed to work on something else first.  If "git fetch
origin other", an explicit request about "other" branch, updated an
unrelated "origin/branch" at the same time, you couldn't recover from it
by using "origin/branch@{1}", because reflog is a fairly recent invention.

An explicit "git fetch origin other" is a way to prevent such an update
from happening.  It does not update anything in refs/ hierarchy, even when
you have configured to make an implicit 'git fetch $there' make a copy of
$this_ref somewhere in your refs/remotes/$there/ hierarchy in .git/config
(back then the same information came from .git/remotes).

Because we have reflogs on by default, and refs/remotes/ is a separate
hierarchy that is read-only from the local user's point of view, I think
the 'explicit fetch' syntax, as a way to stop tracking branches from
getting updated, ceased to be useful these days.

^ permalink raw reply

* Re: [PATCH v3 5/6] transport-helper.c::push_refs(): ignore  helper-reported status if ref is not to be pushed
From: Tay Ray Chuan @ 2010-01-08  1:04 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Shawn O. Pearce, Daniel Barkalow, Junio C Hamano
In-Reply-To: <20100107054120.84972788.rctay89@gmail.com>

Hi,

On Thu, Jan 7, 2010 at 5:41 AM, Tay Ray Chuan <rctay89@gmail.com> wrote:
> Regarding this point, I now think that we should ignore the
> helper-reported status only if that status is none, and continue
> updating the ref status in the top-level transport if the helper did
> push successfully/failed, even if we didn't tell it to push:
>
> @@ -429,7 +429,7 @@ static int push_refs(struct transport *transport,
>
>                ref->status = status;
>                ref->remote_status = msg;
> -               if (ref->status == REF_STATUS_NONE) {
> +               if (ref->status == REF_STATUS_NONE && status == REF_STATUS_NONE) {
>                        ref->status = status;
>                        ref->remote_status = msg;
>                } else {

sorry for this broken hunk. I'll be re-sending shortly to make things clearer.

-- 
Cheers,
Ray Chuan

^ permalink raw reply

* Two versions of a project in one GIT repository
From: Kacper @ 2010-01-08  1:06 UTC (permalink / raw)
  To: git


Hi all,

I have two versions of one project in one local git repository. I have to
commit this repository into 2 remote repositories, one for each version;

LOCAL GIT(V1/V2) -> REMOTE GIT(V1), REMOTE GIT(V2)

I have some files in the LOCAL GIT repository which should only go to REMOTE
GIT(V1) and other should only go to REMOTE GIT(V2). Now I commit full local
repository to both remotes. Can I only commit some files to REMOTE1?

I need to have both version of the project in one repository, but would like
to have an options to divide history a bit. I do not think that any
branching can help as then I would have to make the same changes to both
branches mostly. Most of the code, 90% of the code is the same for VER 1 and
VER 2. New code is usually the same for both versions.

THANK YOU,

Kacper

-- 
View this message in context: http://n2.nabble.com/Two-versions-of-a-project-in-one-GIT-repository-tp4269785p4269785.html
Sent from the git mailing list archive at Nabble.com.

^ permalink raw reply

* [PATCH v4 0/6] transport: catch non-fast forwards
From: Tay Ray Chuan @ 2010-01-08  2:12 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Shawn O. Pearce
In-Reply-To: <20091204102039.GB27495@coredump.intra.peff.net>

Junio, this is re-roll of the 'tr/http-push-ref-status' branch in 'pu'.

Jeff, please don't see this re-roll as me assuming you gave your go-
ahead for the latest discussion; I didn't, I thought squashing in the
hunks I mentioned would make things easier for you, rather than having
them floating around.

Summary:
  This patch series applies on top of 'next', and deals with alerting
  the user to rejected non-fast-forward pushes when using helpers
  (smart).

  Previously, git silently exited. This situation involves the curl
  helper and the smart protocol. The non-fast-forward push is only
  detected when curl executes the rpc client (git-send-pack). Now, we
  detect it before telling the helper to push.

  The series also remedies the scenario where a user would not be aware
  of rejected non-fast-forward pushes.

  It occurs when
    1) there are one or more pushes that succeed and
    2) there are one or more rejected non-fast-forward pushes that
	   involve refs that cannot be matched without explicit refspecs.

  This is due to the re-marking of ref status in transport-helper.c::
  push_refs() when interacting with the remote helper.

  If only non-matched, non-fast-forward refs are involved (ie.
  condition #2 is present without #1), then the situtation does not
  occur - no 'push' commands are passed to the remote helper, no
  interaction with the helper takes place, and no re-marking of ref
  status takes place. The user will be alerted to the rejected
  non-fast-forward push.

  If both are present, re-marking occurs. Even if a ref was not part
  of a 'push' command to the helper, 'ok'/'error' status reports might
  be made for it, since the remote helper does ref matching on its
  side. This led to refs that cannot be matched without an explicit
  refspec marked as REF_STATUS_REJECT_NONFASTFORWARD to be re-marked
  REF_STATUS_NONE.

  (Note: helpers fail to match refs as explicit refspecs are always
  available to the top-level transport mechanism, but only on a need-
  to-know basis to the remote helper via a 'push' command when a ref
  is to be pushed.)

  Interestingly, it is possible for a user to be forever unaware of
  the rejected push if the user relies on information from git push
  alone. As long as the user ensures that one or more other pushes are
  successful (eg. change a tracked ref fast-forwardedly) between the
  execution of git push, the rejected non-fast-forward push won't be
  reported.

Changes from v3:
 - reworded commit message for the test in patch 2
 - added comment on what the switch block is checking for in patch 3
 - changed condition under which ref status reported by remote helper
   is ignored in patch 5

Tay Ray Chuan (6):
  t5541-http-push.sh: add tests for non-fast-forward pushes
  t5541-http-push.sh: add test for unmatched, non-fast-forwarded refs
  refactor ref status logic for pushing
  transport.c::transport_push(): make ref status affect return value
  transport-helper.c::push_refs(): ignore helper-reported status if ref
    is not to be pushed
  transport-helper.c::push_refs(): emit "no refs" error message

 builtin-send-pack.c  |   51 +++++++++++--------------------------------------
 remote.c             |   50 +++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h             |    2 +
 t/t5541-http-push.sh |   44 +++++++++++++++++++++++++++++++++++++++++++
 transport-helper.c   |   28 +++++++++++++++++++-------
 transport.c          |   11 ++++++++-
 6 files changed, 137 insertions(+), 49 deletions(-)

^ permalink raw reply

* [PATCH v4 1/6] t5541-http-push.sh: add tests for non-fast-forward pushes
From: Tay Ray Chuan @ 2010-01-08  2:12 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Shawn O. Pearce
In-Reply-To: <1262916765-3728-1-git-send-email-rctay89@gmail.com>

Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
---
 t/t5541-http-push.sh |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
index 2a58d0c..f49c7c4 100755
--- a/t/t5541-http-push.sh
+++ b/t/t5541-http-push.sh
@@ -88,5 +88,28 @@ test_expect_success 'used receive-pack service' '
 	test_cmp exp act
 '
 
+test_expect_success 'non-fast-forward push fails' '
+	cd "$ROOT_PATH"/test_repo_clone &&
+	git checkout master &&
+	echo "changed" > path2 &&
+	git commit -a -m path2 --amend &&
+
+	HEAD=$(git rev-parse --verify HEAD) &&
+	!(git push -v origin >output 2>&1) &&
+	(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+	 test $HEAD != $(git rev-parse --verify HEAD))
+'
+
+test_expect_failure 'non-fast-forward push show ref status' '
+	grep "^ ! \[rejected\][ ]*master -> master (non-fast-forward)$" output
+'
+
+test_expect_failure 'non-fast-forward push shows help message' '
+	grep \
+"To prevent you from losing history, non-fast-forward updates were rejected
+Merge the remote changes before pushing again.  See the '"'non-fast-forward'"'
+section of '"'git push --help'"' for details." output
+'
+
 stop_httpd
 test_done
-- 
1.6.6.341.ga7aec

^ permalink raw reply related

* [PATCH v4 2/6] t5541-http-push.sh: add test for unmatched, non-fast-forwarded refs
From: Tay Ray Chuan @ 2010-01-08  2:12 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Shawn O. Pearce
In-Reply-To: <1262916765-3728-2-git-send-email-rctay89@gmail.com>

Some refs can only be matched to a remote ref with an explicit refspec.
When such a ref is a non-fast-forward of its remote ref,  test that
pushing them (with the explicit refspec specified) fails with a non-
fast-foward-type error (viz. printing of ref status and help message).

Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
---

Changed from v3:
 - Reworded commit message
 - Reword the comments
 - Used '*' instead of '\+' for grep expressions
 - Used [a-f0-9] instead of [a-z0-9] for matching hexadecimals
 - Used ' ' instead of '[ ]' for matching SP

 t/t5541-http-push.sh |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
index f49c7c4..cc740fe 100755
--- a/t/t5541-http-push.sh
+++ b/t/t5541-http-push.sh
@@ -111,5 +111,26 @@ Merge the remote changes before pushing again.  See the '"'non-fast-forward'"'
 section of '"'git push --help'"' for details." output
 '

+test_expect_failure 'push fails for non-fast-forward refs unmatched by remote helper' '
+	# create a dissimilarly-named remote ref so that git is unable to match the
+	# two refs (viz. local, remote) unless an explicit refspec is provided.
+	git push origin master:retsam
+
+	echo "change changed" > path2 &&
+	git commit -a -m path2 --amend &&
+
+	# push master too; this ensures there is at least one '"'push'"' command to
+	# the remote helper and triggers interaction with the helper.
+	!(git push -v origin +master master:retsam >output 2>&1) &&
+
+	grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
+	grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output &&
+
+	grep \
+"To prevent you from losing history, non-fast-forward updates were rejected
+Merge the remote changes before pushing again.  See the '"'non-fast-forward'"'
+section of '"'git push --help'"' for details." output
+'
+
 stop_httpd
 test_done
--
1.6.6.341.ga7aec

^ permalink raw reply related

* [PATCH v4 3/6] refactor ref status logic for pushing
From: Tay Ray Chuan @ 2010-01-08  2:12 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Shawn O. Pearce
In-Reply-To: <1262916765-3728-3-git-send-email-rctay89@gmail.com>

Move the logic that detects up-to-date and non-fast-forward refs to a
new function in remote.[ch], set_ref_status_for_push().

Make transport_push() invoke set_ref_status_for_push() before invoking
the push_refs() implementation. (As a side-effect, the push_refs()
implementation in transport-helper.c now knows of non-fast-forward
pushes.)

Removed logic for detecting up-to-date refs from the push_refs()
implementation in transport-helper.c, as transport_push() has already
done so for it.

Make cmd_send_pack() invoke set_ref_status_for_push() before invoking
send_pack(), as transport_push() can't do it for send_pack() here.

Mark the test on the return status of non-fast-forward push to fail.
Git now exits with success, as transport.c::transport_push() does not
check for refs with status REF_STATUS_REJECT_NONFASTFORWARD nor does it
indicate rejected pushes with its return value.

Mark the test for ref status to succeed. As mentioned earlier, refs
might be marked as non-fast-forwards, triggering the push status
printing mechanism in transport.c.

Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
---
 builtin-send-pack.c  |   51 +++++++++++--------------------------------------
 remote.c             |   50 +++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h             |    2 +
 t/t5541-http-push.sh |    4 +-
 transport-helper.c   |   14 ++++++------
 transport.c          |    4 +++
 6 files changed, 77 insertions(+), 48 deletions(-)

diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 8fffdbf..76c7206 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -406,50 +406,20 @@ int send_pack(struct send_pack_args *args,
 	 */
 	new_refs = 0;
 	for (ref = remote_refs; ref; ref = ref->next) {
-
-		if (ref->peer_ref)
-			hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
-		else if (!args->send_mirror)
+		if (!ref->peer_ref && !args->send_mirror)
 			continue;
 
-		ref->deletion = is_null_sha1(ref->new_sha1);
-		if (ref->deletion && !allow_deleting_refs) {
-			ref->status = REF_STATUS_REJECT_NODELETE;
-			continue;
-		}
-		if (!ref->deletion &&
-		    !hashcmp(ref->old_sha1, ref->new_sha1)) {
-			ref->status = REF_STATUS_UPTODATE;
+		/* Check for statuses set by set_ref_status_for_push() */
+		switch (ref->status) {
+		case REF_STATUS_REJECT_NONFASTFORWARD:
+		case REF_STATUS_UPTODATE:
 			continue;
+		default:
+			; /* do nothing */
 		}
 
-		/* This part determines what can overwrite what.
-		 * The rules are:
-		 *
-		 * (0) you can always use --force or +A:B notation to
-		 *     selectively force individual ref pairs.
-		 *
-		 * (1) if the old thing does not exist, it is OK.
-		 *
-		 * (2) if you do not have the old thing, you are not allowed
-		 *     to overwrite it; you would not know what you are losing
-		 *     otherwise.
-		 *
-		 * (3) if both new and old are commit-ish, and new is a
-		 *     descendant of old, it is OK.
-		 *
-		 * (4) regardless of all of the above, removing :B is
-		 *     always allowed.
-		 */
-
-		ref->nonfastforward =
-		    !ref->deletion &&
-		    !is_null_sha1(ref->old_sha1) &&
-		    (!has_sha1_file(ref->old_sha1)
-		      || !ref_newer(ref->new_sha1, ref->old_sha1));
-
-		if (ref->nonfastforward && !ref->force && !args->force_update) {
-			ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+		if (ref->deletion && !allow_deleting_refs) {
+			ref->status = REF_STATUS_REJECT_NODELETE;
 			continue;
 		}
 
@@ -673,6 +643,9 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 	if (match_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
 		return -1;
 
+	set_ref_status_for_push(remote_refs, args.send_mirror,
+		args.force_update);
+
 	ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
 
 	if (helper_status)
diff --git a/remote.c b/remote.c
index e3afecd..c70181c 100644
--- a/remote.c
+++ b/remote.c
@@ -1247,6 +1247,56 @@ int match_refs(struct ref *src, struct ref **dst,
 	return 0;
 }
 
+void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
+	int force_update)
+{
+	struct ref *ref;
+
+	for (ref = remote_refs; ref; ref = ref->next) {
+		if (ref->peer_ref)
+			hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+		else if (!send_mirror)
+			continue;
+
+		ref->deletion = is_null_sha1(ref->new_sha1);
+		if (!ref->deletion &&
+			!hashcmp(ref->old_sha1, ref->new_sha1)) {
+			ref->status = REF_STATUS_UPTODATE;
+			continue;
+		}
+
+		/* This part determines what can overwrite what.
+		 * The rules are:
+		 *
+		 * (0) you can always use --force or +A:B notation to
+		 *     selectively force individual ref pairs.
+		 *
+		 * (1) if the old thing does not exist, it is OK.
+		 *
+		 * (2) if you do not have the old thing, you are not allowed
+		 *     to overwrite it; you would not know what you are losing
+		 *     otherwise.
+		 *
+		 * (3) if both new and old are commit-ish, and new is a
+		 *     descendant of old, it is OK.
+		 *
+		 * (4) regardless of all of the above, removing :B is
+		 *     always allowed.
+		 */
+
+		ref->nonfastforward =
+			!ref->deletion &&
+			!is_null_sha1(ref->old_sha1) &&
+			(!has_sha1_file(ref->old_sha1)
+			  || !ref_newer(ref->new_sha1, ref->old_sha1));
+
+		if (ref->nonfastforward && !ref->force && !force_update) {
+			ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+			continue;
+		}
+	}
+}
+
 struct branch *branch_get(const char *name)
 {
 	struct branch *ret;
diff --git a/remote.h b/remote.h
index 8b7ecf9..6e13643 100644
--- a/remote.h
+++ b/remote.h
@@ -98,6 +98,8 @@ char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
 
 int match_refs(struct ref *src, struct ref **dst,
 	       int nr_refspec, const char **refspec, int all);
+void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
+	int force_update);
 
 /*
  * Given a list of the remote refs and the specification of things to
diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
index cc740fe..6d92196 100755
--- a/t/t5541-http-push.sh
+++ b/t/t5541-http-push.sh
@@ -88,7 +88,7 @@ test_expect_success 'used receive-pack service' '
 	test_cmp exp act
 '
 
-test_expect_success 'non-fast-forward push fails' '
+test_expect_failure 'non-fast-forward push fails' '
 	cd "$ROOT_PATH"/test_repo_clone &&
 	git checkout master &&
 	echo "changed" > path2 &&
@@ -100,7 +100,7 @@ test_expect_success 'non-fast-forward push fails' '
 	 test $HEAD != $(git rev-parse --verify HEAD))
 '
 
-test_expect_failure 'non-fast-forward push show ref status' '
+test_expect_success 'non-fast-forward push show ref status' '
 	grep "^ ! \[rejected\][ ]*master -> master (non-fast-forward)$" output
 '
 
diff --git a/transport-helper.c b/transport-helper.c
index 11f3d7e..7c9b569 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -329,16 +329,16 @@ static int push_refs(struct transport *transport,
 		return 1;
 
 	for (ref = remote_refs; ref; ref = ref->next) {
-		if (ref->peer_ref)
-			hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
-		else if (!mirror)
+		if (!ref->peer_ref && !mirror)
 			continue;
 
-		ref->deletion = is_null_sha1(ref->new_sha1);
-		if (!ref->deletion &&
-			!hashcmp(ref->old_sha1, ref->new_sha1)) {
-			ref->status = REF_STATUS_UPTODATE;
+		/* Check for statuses set by set_ref_status_for_push() */
+		switch (ref->status) {
+		case REF_STATUS_REJECT_NONFASTFORWARD:
+		case REF_STATUS_UPTODATE:
 			continue;
+		default:
+			; /* do nothing */
 		}
 
 		if (force_all)
diff --git a/transport.c b/transport.c
index 3eea836..12c4423 100644
--- a/transport.c
+++ b/transport.c
@@ -887,6 +887,10 @@ int transport_push(struct transport *transport,
 			return -1;
 		}
 
+		set_ref_status_for_push(remote_refs,
+			flags & TRANSPORT_PUSH_MIRROR,
+			flags & TRANSPORT_PUSH_FORCE);
+
 		ret = transport->push_refs(transport, remote_refs, flags);
 
 		if (!quiet || push_had_errors(remote_refs))
-- 
1.6.6.341.ga7aec

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox