Git development
 help / color / mirror / Atom feed
* [JGIT PATCH 0/4] Avoid using 1280 file descriptors
From: Shawn O. Pearce @ 2009-03-17  1:16 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git

This is a small series to teach WindowCache not to use 1280 file
descriptors by default.  Most JVMs won't have a ulimit that large,
resulting in out of file errors if the WindowCache actually tries
to fully populate itself.

Shawn O. Pearce (4):
  Refactor WindowCache.reconfigure() to take a configuration object
  Update EGit plugin to use WindowCacheConfig
  Cap the number of open files in the WindowCache
  Teach WindowCacheConfig to read core.packedgit* settings from config

 .../spearce/egit/core/project/GitProjectData.java  |   12 +-
 .../org/spearce/jgit/lib/RepositoryTestCase.java   |    8 +-
 .../org/spearce/jgit/lib/UnpackedObjectCache.java  |    7 +-
 .../src/org/spearce/jgit/lib/WindowCache.java      |  119 ++++++++++----
 .../org/spearce/jgit/lib/WindowCacheConfig.java    |  170 ++++++++++++++++++++
 5 files changed, 271 insertions(+), 45 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java

^ permalink raw reply

* [JGIT PATCH 1/4] Refactor WindowCache.reconfigure() to take a configuration object
From: Shawn O. Pearce @ 2009-03-17  1:16 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1237252570-8596-1-git-send-email-spearce@spearce.org>

This makes it safer for applications to be calling reconfigure()
should we ever add more controllable parameters to cache.  It may
also leave the door open for more common option handling, such as
reading from ~/.gitconfig in a standard way across applications
built upon JGit.  We could also add sanity check functions to the
new configuration object, allowing applications to inquire about
the validity before installing it.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../org/spearce/jgit/lib/RepositoryTestCase.java   |    8 +-
 .../org/spearce/jgit/lib/UnpackedObjectCache.java  |    7 +-
 .../src/org/spearce/jgit/lib/WindowCache.java      |   54 +++++---
 .../org/spearce/jgit/lib/WindowCacheConfig.java    |  134 ++++++++++++++++++++
 4 files changed, 178 insertions(+), 25 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java

diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java
index 4e56b38..5d8c056 100644
--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java
@@ -113,8 +113,12 @@ public String getProperty(String key) {
 	 * Configure JGit before setting up test repositories.
 	 */
 	protected void configure() {
-		packedGitMMAP = "true".equals(System.getProperty("jgit.junit.usemmmap"));
-		WindowCache.reconfigure(128*1024, 8192, packedGitMMAP, 8192);
+		final WindowCacheConfig c = new WindowCacheConfig();
+		c.setPackedGitLimit(128 * WindowCacheConfig.KB);
+		c.setPackedGitWindowSize(8 * WindowCacheConfig.KB);
+		c.setPackedGitMMAP("true".equals(System.getProperty("jgit.junit.usemmmap")));
+		c.setDeltaBaseCacheLimit(8 * WindowCacheConfig.KB);
+		WindowCache.reconfigure(c);
 	}
 
 	/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/UnpackedObjectCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/UnpackedObjectCache.java
index 677b3a7..13861bf 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/UnpackedObjectCache.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/UnpackedObjectCache.java
@@ -42,8 +42,6 @@
 class UnpackedObjectCache {
 	private static final int CACHE_SZ = 1024;
 
-	private static final int MB = 1024 * 1024;
-
 	private static final SoftReference<Entry> DEAD;
 
 	private static int hash(final long position) {
@@ -62,14 +60,15 @@ private static int hash(final long position) {
 
 	static {
 		DEAD = new SoftReference<Entry>(null);
-		maxByteCount = 10 * MB;
+		maxByteCount = new WindowCacheConfig().getDeltaBaseCacheLimit();
 
 		cache = new Slot[CACHE_SZ];
 		for (int i = 0; i < CACHE_SZ; i++)
 			cache[i] = new Slot();
 	}
 
-	static synchronized void reconfigure(final int dbLimit) {
+	static synchronized void reconfigure(final WindowCacheConfig cfg) {
+		final int dbLimit = cfg.getDeltaBaseCacheLimit();
 		if (maxByteCount != dbLimit) {
 			maxByteCount = dbLimit;
 			releaseMemory();
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
index 6a650cb..ba1124a 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
@@ -46,10 +46,6 @@
  * the other windowed file access classes.
  */
 public class WindowCache {
-	private static final int KB = 1024;
-
-	private static final int MB = 1024 * KB;
-
 	private static final int bits(int newSize) {
 		if (newSize < 4096)
 			throw new IllegalArgumentException("Invalid window size");
@@ -77,10 +73,11 @@ private static final int bits(int newSize) {
 	private static int openByteCount;
 
 	static {
-		maxByteCount = 10 * MB;
-		windowSizeShift = bits(8 * KB);
+		final WindowCacheConfig c = new WindowCacheConfig();
+		maxByteCount = c.getPackedGitLimit();
+		windowSizeShift = bits(c.getPackedGitWindowSize());
 		windowSize = 1 << windowSizeShift;
-		mmap = false;
+		mmap = c.isPackedGitMMAP();
 		cache = new ByteWindow[cacheTableSize()];
 		clearedWindowQueue = new ReferenceQueue<Object>();
 	}
@@ -104,34 +101,53 @@ private static int cacheTableSize() {
 	 *            true to enable use of mmap when creating windows.
 	 * @param deltaBaseCacheLimit
 	 *            number of bytes to hold in the delta base cache.
+	 * @deprecated Use {@link WindowCacheConfig} instead.
 	 */
 	public static void reconfigure(final int packedGitLimit,
 			final int packedGitWindowSize, final boolean packedGitMMAP,
 			final int deltaBaseCacheLimit) {
-		reconfigureImpl(packedGitLimit, packedGitWindowSize, packedGitMMAP);
-		UnpackedObjectCache.reconfigure(deltaBaseCacheLimit);
+		final WindowCacheConfig c = new WindowCacheConfig();
+		c.setPackedGitLimit(packedGitLimit);
+		c.setPackedGitWindowSize(packedGitWindowSize);
+		c.setPackedGitMMAP(packedGitMMAP);
+		c.setDeltaBaseCacheLimit(deltaBaseCacheLimit);
+		reconfigure(c);
+	}
+
+	/**
+	 * Modify the configuration of the window cache.
+	 * <p>
+	 * The new configuration is applied immediately. If the new limits are
+	 * smaller than what what is currently cached, older entries will be purged
+	 * as soon as possible to allow the cache to meet the new limit.
+	 *
+	 * @param cfg
+	 *            the new window cache configuration.
+	 */
+	public static void reconfigure(final WindowCacheConfig cfg) {
+		reconfigureImpl(cfg);
+		UnpackedObjectCache.reconfigure(cfg);
 	}
 
-	private static synchronized void reconfigureImpl(final int packedGitLimit,
-			final int packedGitWindowSize, final boolean packedGitMMAP) {
+	private static synchronized void reconfigureImpl(final WindowCacheConfig cfg) {
 		boolean prune = false;
 		boolean evictAll = false;
 
-		if (maxByteCount < packedGitLimit) {
-			maxByteCount = packedGitLimit;
-		} else if (maxByteCount > packedGitLimit) {
-			maxByteCount = packedGitLimit;
+		if (maxByteCount < cfg.getPackedGitLimit()) {
+			maxByteCount = cfg.getPackedGitLimit();
+		} else if (maxByteCount > cfg.getPackedGitLimit()) {
+			maxByteCount = cfg.getPackedGitLimit();
 			prune = true;
 		}
 
-		if (bits(packedGitWindowSize) != windowSizeShift) {
-			windowSizeShift = bits(packedGitWindowSize);
+		if (bits(cfg.getPackedGitWindowSize()) != windowSizeShift) {
+			windowSizeShift = bits(cfg.getPackedGitWindowSize());
 			windowSize = 1 << windowSizeShift;
 			evictAll = true;
 		}
 
-		if (mmap != packedGitMMAP) {
-			mmap = packedGitMMAP;
+		if (mmap != cfg.isPackedGitMMAP()) {
+			mmap = cfg.isPackedGitMMAP();
 			evictAll = true;
 		}
 
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
new file mode 100644
index 0000000..b4c4638
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009, Google Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.lib;
+
+/** Configuration parameters for {@link WindowCache}. */
+public class WindowCacheConfig {
+	/** 1024 (number of bytes in one kibibyte/kilobyte) */
+	public static final int KB = 1024;
+
+	/** 1024 {@link #KB} (number of bytes in one mebibyte/megabyte) */
+	public static final int MB = 1024 * KB;
+
+	private int packedGitLimit;
+
+	private int packedGitWindowSize;
+
+	private boolean packedGitMMAP;
+
+	private int deltaBaseCacheLimit;
+
+	/** Create a default configuration. */
+	public WindowCacheConfig() {
+		packedGitLimit = 10 * MB;
+		packedGitWindowSize = 8 * KB;
+		packedGitMMAP = false;
+		deltaBaseCacheLimit = 10 * MB;
+	}
+
+	/**
+	 * @return maximum number bytes of heap memory to dedicate to caching pack
+	 *         file data. <b>Default is 10 MB.</b>
+	 */
+	public int getPackedGitLimit() {
+		return packedGitLimit;
+	}
+
+	/**
+	 * @param newLimit
+	 *            maximum number bytes of heap memory to dedicate to caching
+	 *            pack file data.
+	 */
+	public void setPackedGitLimit(final int newLimit) {
+		packedGitLimit = newLimit;
+	}
+
+	/**
+	 * @return size in bytes of a single window mapped or read in from the pack
+	 *         file. <b>Default is 8 KB.</b>
+	 */
+	public int getPackedGitWindowSize() {
+		return packedGitWindowSize;
+	}
+
+	/**
+	 * @param newSize
+	 *            size in bytes of a single window read in from the pack file.
+	 */
+	public void setPackedGitWindowSize(final int newSize) {
+		packedGitWindowSize = newSize;
+	}
+
+	/**
+	 * @return true enables use of Java NIO virtual memory mapping for windows;
+	 *         false reads entire window into a byte[] with standard read calls.
+	 *         <b>Default false.</b>
+	 */
+	public boolean isPackedGitMMAP() {
+		return packedGitMMAP;
+	}
+
+	/**
+	 * @param usemmap
+	 *            true enables use of Java NIO virtual memory mapping for
+	 *            windows; false reads entire window into a byte[] with standard
+	 *            read calls.
+	 */
+	public void setPackedGitMMAP(final boolean usemmap) {
+		packedGitMMAP = usemmap;
+	}
+
+	/**
+	 * @return maximum number of bytes to cache in {@link UnpackedObjectCache}
+	 *         for inflated, recently accessed objects, without delta chains.
+	 *         <b>Default 10 MB.</b>
+	 */
+	public int getDeltaBaseCacheLimit() {
+		return deltaBaseCacheLimit;
+	}
+
+	/**
+	 * @param newLimit
+	 *            maximum number of bytes to cache in
+	 *            {@link UnpackedObjectCache} for inflated, recently accessed
+	 *            objects, without delta chains.
+	 */
+	public void setDeltaBaseCacheLimit(final int newLimit) {
+		deltaBaseCacheLimit = newLimit;
+	}
+}
-- 
1.6.2.1.286.g8173

^ permalink raw reply related

* [JGIT PATCH 2/4] Update EGit plugin to use WindowCacheConfig
From: Shawn O. Pearce @ 2009-03-17  1:16 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1237252570-8596-2-git-send-email-spearce@spearce.org>

Its more flexible for future additions to the parameters.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../spearce/egit/core/project/GitProjectData.java  |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java b/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java
index 8b72818..31d5483 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java
@@ -42,6 +42,7 @@
 import org.spearce.egit.core.GitProvider;
 import org.spearce.jgit.lib.Repository;
 import org.spearce.jgit.lib.WindowCache;
+import org.spearce.jgit.lib.WindowCacheConfig;
 
 /**
  * This class keeps information about how a project is mapped to
@@ -229,12 +230,13 @@ private synchronized static Repository lookupRepository(final File gitDir)
 	 * Update the settings for the global window cache of the workspace.
 	 */
 	public static void reconfigureWindowCache() {
+		final WindowCacheConfig c = new WindowCacheConfig();
 		Preferences p = Activator.getDefault().getPluginPreferences();
-		int wLimit = p.getInt(GitCorePreferences.core_packedGitLimit);
-		int wSize = p.getInt(GitCorePreferences.core_packedGitWindowSize);
-		boolean mmap = p.getBoolean(GitCorePreferences.core_packedGitMMAP);
-		int dbLimit = p.getInt(GitCorePreferences.core_deltaBaseCacheLimit);
-		WindowCache.reconfigure(wLimit, wSize, mmap, dbLimit);
+		c.setPackedGitLimit(p.getInt(GitCorePreferences.core_packedGitLimit));
+		c.setPackedGitWindowSize(p.getInt(GitCorePreferences.core_packedGitWindowSize));
+		c.setPackedGitMMAP(p.getBoolean(GitCorePreferences.core_packedGitMMAP));
+		c.setDeltaBaseCacheLimit(p.getInt(GitCorePreferences.core_deltaBaseCacheLimit));
+		WindowCache.reconfigure(c);
 	}
 
 	private final IProject project;
-- 
1.6.2.1.286.g8173

^ permalink raw reply related

* [JGIT PATCH 4/4] Teach WindowCacheConfig to read core.packedgit* settings from config
From: Shawn O. Pearce @ 2009-03-17  1:16 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1237252570-8596-4-git-send-email-spearce@spearce.org>

This may help applications which want to read configuration from
the current repository, or from ~/.gitconfig when picking the access
strategy for the current process.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../org/spearce/jgit/lib/WindowCacheConfig.java    |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
index d906a7c..ea28164 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
@@ -151,4 +151,20 @@ public int getDeltaBaseCacheLimit() {
 	public void setDeltaBaseCacheLimit(final int newLimit) {
 		deltaBaseCacheLimit = newLimit;
 	}
+
+	/**
+	 * Update properties by setting fields from the configuration.
+	 * <p>
+	 * If a property is not defined in the configuration, then it is left
+	 * unmodified.
+	 *
+	 * @param rc configuration to read properties from.
+	 */
+	public void fromConfig(final RepositoryConfig rc) {
+		setPackedGitOpenFiles(rc.getInt("core", null, "packedgitopenfiles", getPackedGitOpenFiles()));
+		setPackedGitLimit(rc.getInt("core", null, "packedgitlimit", getPackedGitLimit()));
+		setPackedGitWindowSize(rc.getInt("core", null, "packedgitwindowsize", getPackedGitWindowSize()));
+		setPackedGitMMAP(rc.getBoolean("core", null, "packedgitmmap", isPackedGitMMAP()));
+		setDeltaBaseCacheLimit(rc.getInt("core", null, "deltabasecachelimit", getDeltaBaseCacheLimit()));
+	}
 }
-- 
1.6.2.1.286.g8173

^ permalink raw reply related

* [JGIT PATCH 3/4] Cap the number of open files in the WindowCache
From: Shawn O. Pearce @ 2009-03-17  1:16 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1237252570-8596-3-git-send-email-spearce@spearce.org>

The default WindowCache configuration is:

  packedGitLimit:      10 MB
  packedGitWindowSize:  8 KB

10 MB / 8 KB allows up to 1280 windows permitted in the WindowCache
at any given time.  If every window came from a unique pack file, we
need 1280 file descriptors just for the resources in the WindowCache.
For most applications this is way beyond the hard limit configured
for the host JVM, causing java.io.IOException("Too many open files")
from possibly any part of JGit or the host application.

Specifically, I ran into this problem in Gerrit Code Review, where we
commonly see hundreds of very small pack files spread over hundreds
of Git repositories, all accessed from a persistent JVM that is also
hosting an SSH daemon and a web server.  The aggressive caching of
windows in the WindowCache and of Repository objects in Gerrit's
own RepositoryCache caused us to retain far too many tiny pack files.

We now set the limit at 128 open files, assuming this is a reasonable
limit for most applications using the library.  Git repositories tend
to be in the handful of packs/repository (e.g. <10 packs/repository)
and applications using JGit tend to access only a handful of Git
repositories at a time (e.g. <10 repositories/JVM).

If we detect a file open failure while opening a pack we halve
the number of permitted open files and try again, until we reach
a lower bound of 16 open files.  Needing to go lower may indicate
a file descriptor leak in the host application.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/lib/WindowCache.java      |   65 +++++++++++++++-----
 .../org/spearce/jgit/lib/WindowCacheConfig.java    |   20 ++++++
 2 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
index ba1124a..13912a7 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
@@ -54,6 +54,8 @@ private static final int bits(int newSize) {
 		return Integer.numberOfTrailingZeros(newSize);
 	}
 
+	private static int maxFileCount;
+
 	private static int maxByteCount;
 
 	private static int windowSize;
@@ -70,10 +72,13 @@ private static final int bits(int newSize) {
 
 	private static ByteWindow lruTail;
 
+	private static int openFileCount;
+
 	private static int openByteCount;
 
 	static {
 		final WindowCacheConfig c = new WindowCacheConfig();
+		maxFileCount = c.getPackedGitOpenFiles();
 		maxByteCount = c.getPackedGitLimit();
 		windowSizeShift = bits(c.getPackedGitWindowSize());
 		windowSize = 1 << windowSizeShift;
@@ -133,6 +138,13 @@ private static synchronized void reconfigureImpl(final WindowCacheConfig cfg) {
 		boolean prune = false;
 		boolean evictAll = false;
 
+		if (maxFileCount < cfg.getPackedGitOpenFiles())
+			maxFileCount = cfg.getPackedGitOpenFiles();
+		else if (maxFileCount > cfg.getPackedGitOpenFiles()) {
+			maxFileCount = cfg.getPackedGitOpenFiles();
+			prune = true;
+		}
+
 		if (maxByteCount < cfg.getPackedGitLimit()) {
 			maxByteCount = cfg.getPackedGitLimit();
 		} else if (maxByteCount > cfg.getPackedGitLimit()) {
@@ -229,20 +241,37 @@ private static synchronized final void getImpl(final WindowCursor curs,
 		}
 
 		if (wp.openCount == 0) {
-			try {
-				wp.openCount = 1;
-				wp.cacheOpen();
-			} catch (IOException ioe) {
-				wp.openCount = 0;
-				throw ioe;
-			} catch (RuntimeException ioe) {
-				wp.openCount = 0;
-				throw ioe;
-			} catch (Error ioe) {
-				wp.openCount = 0;
-				throw ioe;
-			} finally {
-				wp.openCount--;
+			TRY_OPEN: for (;;) {
+				try {
+					openFileCount++;
+					releaseMemory();
+					runClearedWindowQueue();
+					wp.openCount = 1;
+					wp.cacheOpen();
+					break;
+				} catch (IOException ioe) {
+					openFileCount--;
+					if ("Too many open files".equals(ioe.getMessage())
+							&& maxFileCount > 16) {
+						// We may be able to recover by halving our limit
+						// and trying again.
+						//
+						maxFileCount = Math.max(16, maxFileCount >> 2);
+						continue TRY_OPEN;
+					}
+					wp.openCount = 0;
+					throw ioe;
+				} catch (RuntimeException ioe) {
+					openFileCount--;
+					wp.openCount = 0;
+					throw ioe;
+				} catch (Error ioe) {
+					openFileCount--;
+					wp.openCount = 0;
+					throw ioe;
+				} finally {
+					wp.openCount--;
+				}
 			}
 
 			// The cacheOpen may have mapped the window we are trying to
@@ -278,6 +307,7 @@ private static synchronized final void getImpl(final WindowCursor curs,
 
 	static synchronized void markLoaded(final ByteWindow w) {
 		if (--w.provider.openCount == 0) {
+			openFileCount--;
 			w.provider.cacheClose();
 		}
 	}
@@ -291,13 +321,17 @@ private static void makeMostRecent(ByteWindow<?> e) {
 
 	private static void releaseMemory() {
 		ByteWindow<?> e = lruTail;
-		while (openByteCount > maxByteCount && e != null) {
+		while (isOverLimit() && e != null) {
 			final ByteWindow<?> p = e.lruPrev;
 			clear(e);
 			e = p;
 		}
 	}
 
+	private static boolean isOverLimit() {
+		return openByteCount > maxByteCount || openFileCount > maxFileCount;
+	}
+
 	/**
 	 * Remove all windows associated with a specific provider.
 	 * <p>
@@ -341,6 +375,7 @@ private static void clear(final ByteWindow<?> e) {
 	private static void unlinkSize(final ByteWindow<?> e) {
 		if (e.sizeActive) {
 			if (--e.provider.openCount == 0) {
+				openFileCount--;
 				e.provider.cacheClose();
 			}
 			openByteCount -= e.size;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
index b4c4638..d906a7c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCacheConfig.java
@@ -45,6 +45,8 @@
 	/** 1024 {@link #KB} (number of bytes in one mebibyte/megabyte) */
 	public static final int MB = 1024 * KB;
 
+	private int packedGitOpenFiles;
+
 	private int packedGitLimit;
 
 	private int packedGitWindowSize;
@@ -55,6 +57,7 @@
 
 	/** Create a default configuration. */
 	public WindowCacheConfig() {
+		packedGitOpenFiles = 128;
 		packedGitLimit = 10 * MB;
 		packedGitWindowSize = 8 * KB;
 		packedGitMMAP = false;
@@ -62,6 +65,23 @@ public WindowCacheConfig() {
 	}
 
 	/**
+	 * @return maximum number of streams to open at a time. Open packs count
+	 *         against the process limits. <b>Default is 128.</b>
+	 */
+	public int getPackedGitOpenFiles() {
+		return packedGitOpenFiles;
+	}
+
+	/**
+	 * @param fdLimit
+	 *            maximum number of streams to open at a time. Open packs count
+	 *            against the process limits
+	 */
+	public void setPackedGitOpenFiles(final int fdLimit) {
+		packedGitOpenFiles = fdLimit;
+	}
+
+	/**
 	 * @return maximum number bytes of heap memory to dedicate to caching pack
 	 *         file data. <b>Default is 10 MB.</b>
 	 */
-- 
1.6.2.1.286.g8173

^ permalink raw reply related

* GIT_WORK_TREE=dir git ls-files --deleted
From: Jonas Bernoulli @ 2009-03-17  1:41 UTC (permalink / raw)
  To: git

Hello

git ls-files --deleted seams to be broken when GIT_WORK_TREE is set as
can be observed below.

Instead of just showing deleted files it also shows at least unchanged
and modified files.

I have observed this behaviour with git.git and do not know if
released versions are affected.

#### setup

$ mkdir -p base/worktree
$ cd base/
$ export GIT_DIR=/tmp/base/.git
$ export GIT_WORK_TREE=/tmp/base/worktree
$ git init
Initialized empty Git repository in /tmp/base/.git/
$ touch worktree/deleted worktree/modified worktree/unchanged
$ git add .
$ git commit -m init
[master (root-commit) f4e1bd3] init
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 deleted
 create mode 100644 modified
 create mode 100644 unchanged
$ rm worktree/deleted
$ echo modified > worktree/modified

#### expected result

$ git ls-files --deleted
deleted

#### actual result

$ git ls-files --deleted
deleted
modified
unchanged

#### untracked and out-of-worktree seam to be fine

$ touch worktree/untracked
$ touch not-in-worktree
$ git ls-files --deleted
deleted
modified
unchanged

#### related options / commands seam to be fine

$ git ls-files --modified
deleted
modified
$ git ls-files --others
$ git ls-files --cached
deleted
modified
unchanged
$ git status
# On branch master
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       deleted:    deleted
#       modified:   modified
#
no changes added to commit (use "git add" and/or "git commit -a")

Best regards,

-- Jonas Bernoulli

Ps: Is there a way to show modified files excluding deleted files
other than this?
( git ls-files --deleted; git ls-files --modified ) | uniq --unique
Pps: The description of --others is ambitious, what is "other files"?

^ permalink raw reply

* [JGIT] Pushing the HEAD ref?
From: Daniel Cheng @ 2009-03-17  4:04 UTC (permalink / raw)
  To: git

Hi List,

When I develop the freenet transport, I found the refWriter in
WalkPushConnection never write the HEAD refs, even if this is a new
repository.
Is this the expected behaviour? This cause error when I clone the repository.

Regards,
Daniel Cheng.

^ permalink raw reply

* Re: git-svn rebase can change branches during merge?
From: Kevin Williams @ 2009-03-17  4:34 UTC (permalink / raw)
  To: Jan Krüger; +Cc: git
In-Reply-To: <20090316233641.248f2e81@perceptron>

On Mon, Mar 16, 2009 at 4:36 PM, Jan Krüger <jk@jk.gs> wrote:
> Hi Kevin,
>
>> I've outlined steps where I can reproduce this bug here:
>> http://gist.github.com/80058
>>
>> When using "git svn rebase" and there is a conflict between a local
>> (git) change and an upstream (svn) change, the local git repository is
>> left in a ghost-branch. It shouldn't change branches during a rebase,
>> should it? I also seem to be unable to recover from the merge
>> conflict, but that may be just due to the noob at the keyboard (me).
>
> rebase doesn't actually switch to another branch here, but it does
> detach HEAD. To get back to a state you can work from, it's a simple
> case of following the instructions rebase outputs:
>
> 1) edit conflicted files to fix the conflicts.
> 2) stage new versions of files (e.g. git add file.txt)
> 3) git rebase --continue
>
> Here's what happens:
>
> jast@perceptron 1% cat test.txt
> <<<<<<< HEAD:test.txt
> git svn rebase blows up here
> =======
> hello from svn
> hello from git
>>>>>>>> add to txt file from git:test.txt
> jast@perceptron % git branch
> * (no branch)
>  master
> jast@perceptron % vim test.txt
> [...]
> jast@perceptron % git add test.txt
> jast@perceptron % git rebase --continue
> Applying: add to txt file from git
> jast@perceptron % git branch
> * master
> jast@perceptron %
>
> Make sense?
> -Jan
>

I think so. Thanks for the detailed examples.

I think sometimes I was committing after adding the fixed files, which
would seem to succeed but then the 'git rebase --continue' would blow
up and I couldn't get back to master without 'git rebase --abort'.

Thanks again!


-- 
Cheers,

Kevin Williams

^ permalink raw reply

* Re: [PATCH 0/2] git checkout: one bugfix and one cosmetic change
From: Kris Shannon @ 2009-03-17  4:56 UTC (permalink / raw)
  To: Kjetil Barvik; +Cc: Git Mailing List
In-Reply-To: <cover.1237115791.git.barvik@broadpark.no>

2009/3/15 Kjetil Barvik <barvik@broadpark.no>:
> Just one small bugfix patch, and one small cosmetic change.
>
> By the way, I wonder how often the list of 'Primary Authors' and
> 'Contributors' on the webpage http://git-scm.com/about is updated.
> Should'nt it be updated when a new release, like v1.6.2, is made?
>

I was rather surprised to see my name on that list.  A quick git log
showed my one contribution to git-parse-remote way pack in
August 2005.

I'd forgotten about that and was feeling all warm and fuzzy until I did:
git log -- git-parse-remote

and saw that it was deleted a week later :(

^ permalink raw reply

* [PATCH][v2] http authentication via prompts (with correct line  lengths)
From: Amos King @ 2009-03-17  5:15 UTC (permalink / raw)
  To: git

Junio,

I'm working with Mike on the http auth stuff, and I was testing out
your patch.  I can get it to work for fetch but push is giving me some
grief.  Looking through the code I noticed that online 219 of
http-push.c that http_init is being called with NULL instead of a
remote.  If I pass in the remote then there is no remotre-url.  I've
been digging around and can't find where or when that is being set.
It has been a while since I worked with C but I'd love to jump in and
help out here.  Can you point me in the right direction to get the
remote->url[0] set for the http_auth_init to use?

Thanks,

-- 
Amos King
http://dirtyInformation.com
http://github.com/Adkron
--
Looking for something to do? Visit http://ImThere.com

^ permalink raw reply

* [PATCH 1/4] Documentation: minor grammatical fixes in git-archive.txt.
From: David J. Mellor @ 2009-03-17  6:16 UTC (permalink / raw)
  To: gitster; +Cc: git


Signed-off-by: David J. Mellor <dmellor@whistlingcat.com>
---
 Documentation/git-archive.txt |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 0eeefe0..c1adf59 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -23,7 +23,7 @@ prepended to the filenames in the archive.
 
 'git-archive' behaves differently when given a tree ID versus when
 given a commit ID or tag ID.  In the first case the current time is
-used as modification time of each file in the archive.  In the latter
+used as the modification time of each file in the archive.  In the latter
 case the commit time as recorded in the referenced commit object is
 used instead.  Additionally the commit ID is stored in a global
 extended pax header if the tar format is used; it can be extracted
@@ -52,11 +52,11 @@ OPTIONS
 	Write the archive to <file> instead of stdout.
 
 <extra>::
-	This can be any options that the archiver backend understand.
+	This can be any options that the archiver backend understands.
 	See next section.
 
 --remote=<repo>::
-	Instead of making a tar archive from local repository,
+	Instead of making a tar archive from the local repository,
 	retrieve a tar archive from a remote repository.
 
 --exec=<git-upload-archive>::
@@ -109,7 +109,7 @@ EXAMPLES
 git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
 
 	Create a tar archive that contains the contents of the
-	latest commit on the current branch, and extracts it in
+	latest commit on the current branch, and extract it in the
 	`/var/tmp/junk` directory.
 
 git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
-- 
1.6.2.1

^ permalink raw reply related

* [PATCH 3/4] Documentation: minor grammatical fixes in git-blame.txt.
From: David J. Mellor @ 2009-03-17  6:16 UTC (permalink / raw)
  To: gitster; +Cc: git
In-Reply-To: <1237270577-17261-2-git-send-email-dmellor@whistlingcat.com>


Signed-off-by: David J. Mellor <dmellor@whistlingcat.com>
---
 Documentation/blame-options.txt |    2 +-
 Documentation/git-blame.txt     |   56 +++++++++++++++++++-------------------
 Documentation/mailmap.txt       |   17 +++++------
 3 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt
index 63fc197..1625ffc 100644
--- a/Documentation/blame-options.txt
+++ b/Documentation/blame-options.txt
@@ -39,7 +39,7 @@ of lines before or after the line given by <start>.
 	Show raw timestamp (Default: off).
 
 -S <revs-file>::
-	Use revs from revs-file instead of calling linkgit:git-rev-list[1].
+	Use revisions from revs-file instead of calling linkgit:git-rev-list[1].
 
 --reverse::
 	Walk history forward instead of backward. Instead of showing
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index 4ef54d6..8c7b7b0 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -18,9 +18,9 @@ DESCRIPTION
 Annotates each line in the given file with information from the revision which
 last modified the line. Optionally, start annotating from the given revision.
 
-Also it can limit the range of lines annotated.
+The command can also limit the range of lines annotated.
 
-This report doesn't tell you anything about lines which have been deleted or
+The report does not tell you anything about lines which have been deleted or
 replaced; you need to use a tool such as 'git-diff' or the "pickaxe"
 interface briefly mentioned in the following paragraph.
 
@@ -48,26 +48,26 @@ include::blame-options.txt[]
 	lines between files (see `-C`) and lines moved within a
 	file (see `-M`).  The first number listed is the score.
 	This is the number of alphanumeric characters detected
-	to be moved between or within files.  This must be above
+	as having been moved between or within files.  This must be above
 	a certain threshold for 'git-blame' to consider those lines
 	of code to have been moved.
 
 -f::
 --show-name::
-	Show filename in the original commit.  By default
-	filename is shown if there is any line that came from a
-	file with different name, due to rename detection.
+	Show the filename in the original commit.  By default
+	the filename is shown if there is any line that came from a
+	file with a different name, due to rename detection.
 
 -n::
 --show-number::
-	Show line number in the original commit (Default: off).
+	Show the line number in the original commit (Default: off).
 
 -s::
-	Suppress author name and timestamp from the output.
+	Suppress the author name and timestamp from the output.
 
 -w::
-	Ignore whitespace when comparing parent's version and
-	child's to find where the lines came from.
+	Ignore whitespace when comparing the parent's version and
+	the child's to find where the lines came from.
 
 
 THE PORCELAIN FORMAT
@@ -79,17 +79,17 @@ header at the minimum has the first line which has:
 - 40-byte SHA-1 of the commit the line is attributed to;
 - the line number of the line in the original file;
 - the line number of the line in the final file;
-- on a line that starts a group of line from a different
+- on a line that starts a group of lines from a different
   commit than the previous one, the number of lines in this
   group.  On subsequent lines this field is absent.
 
 This header line is followed by the following information
 at least once for each commit:
 
-- author name ("author"), email ("author-mail"), time
+- the author name ("author"), email ("author-mail"), time
   ("author-time"), and timezone ("author-tz"); similarly
   for committer.
-- filename in the commit the line is attributed to.
+- the filename in the commit that the line is attributed to.
 - the first line of the commit log message ("summary").
 
 The contents of the actual line is output after the above
@@ -100,23 +100,23 @@ header elements later.
 SPECIFYING RANGES
 -----------------
 
-Unlike 'git-blame' and 'git-annotate' in older git, the extent
-of annotation can be limited to both line ranges and revision
+Unlike 'git-blame' and 'git-annotate' in older versions of git, the extent
+of the annotation can be limited to both line ranges and revision
 ranges.  When you are interested in finding the origin for
-ll. 40-60 for file `foo`, you can use `-L` option like these
+lines 40-60 for file `foo`, you can use the `-L` option like so
 (they mean the same thing -- both ask for 21 lines starting at
 line 40):
 
 	git blame -L 40,60 foo
 	git blame -L 40,+21 foo
 
-Also you can use regular expression to specify the line range.
+Also you can use a regular expression to specify the line range:
 
 	git blame -L '/^sub hello {/,/^}$/' foo
 
-would limit the annotation to the body of `hello` subroutine.
+which limits the annotation to the body of the `hello` subroutine.
 
-When you are not interested in changes older than the version
+When you are not interested in changes older than version
 v2.6.18, or changes older than 3 weeks, you can use revision
 range specifiers  similar to 'git-rev-list':
 
@@ -129,7 +129,7 @@ commit v2.6.18 or the most recent commit that is more than 3
 weeks old in the above example) are blamed for that range
 boundary commit.
 
-A particularly useful way is to see if an added file have lines
+A particularly useful way is to see if an added file has lines
 created by copy-and-paste from existing files.  Sometimes this
 indicates that the developer was being sloppy and did not
 refactor the code properly.  You can first find the commit that
@@ -162,26 +162,26 @@ annotated.
 +
 Line numbers count from 1.
 
-. The first time that commit shows up in the stream, it has various
+. The first time that a commit shows up in the stream, it has various
   other information about it printed out with a one-word tag at the
-  beginning of each line about that "extended commit info" (author,
-  email, committer, dates, summary etc).
+  beginning of each line describing the extra commit information (author,
+  email, committer, dates, summary, etc.).
 
-. Unlike Porcelain format, the filename information is always
+. Unlike the Porcelain format, the filename information is always
   given and terminates the entry:
 
 	"filename" <whitespace-quoted-filename-goes-here>
 +
-and thus it's really quite easy to parse for some line- and word-oriented
+and thus it is really quite easy to parse for some line- and word-oriented
 parser (which should be quite natural for most scripting languages).
 +
 [NOTE]
 For people who do parsing: to make it more robust, just ignore any
-lines in between the first and last one ("<sha1>" and "filename" lines)
-where you don't recognize the tag-words (or care about that particular
+lines between the first and last one ("<sha1>" and "filename" lines)
+where you do not recognize the tag words (or care about that particular
 one) at the beginning of the "extended information" lines. That way, if
 there is ever added information (like the commit encoding or extended
-commit commentary), a blame viewer won't ever care.
+commit commentary), a blame viewer will not care.
 
 
 MAPPING AUTHORS
diff --git a/Documentation/mailmap.txt b/Documentation/mailmap.txt
index e25b154..288f04e 100644
--- a/Documentation/mailmap.txt
+++ b/Documentation/mailmap.txt
@@ -5,22 +5,21 @@ canonical real names and email addresses.
 
 In the simple form, each line in the file consists of the canonical
 real name of an author, whitespace, and an email address used in the
-commit (enclosed by '<' and '>') to map to the name. Thus, looks like
-this
+commit (enclosed by '<' and '>') to map to the name. For example:
 --
 	Proper Name <commit@email.xx>
 --
 
-The more complex forms are
+The more complex forms are:
 --
 	<proper@email.xx> <commit@email.xx>
 --
-which allows mailmap to replace only the email part of a commit, and
+which allows mailmap to replace only the email part of a commit, and:
 --
 	Proper Name <proper@email.xx> <commit@email.xx>
 --
 which allows mailmap to replace both the name and the email of a
-commit matching the specified commit email address, and
+commit matching the specified commit email address, and:
 --
 	Proper Name <proper@email.xx> Commit Name <commit@email.xx>
 --
@@ -47,8 +46,8 @@ Jane Doe         <jane@desktop.(none)>
 Joe R. Developer <joe@example.com>
 ------------
 
-Note how we don't need an entry for <jane@laptop.(none)>, because the
-real name of that author is correct already.
+Note how there is no need for an entry for <jane@laptop.(none)>, because the
+real name of that author is already correct.
 
 Example 2: Your repository contains commits from the following
 authors:
@@ -62,7 +61,7 @@ claus <me@company.xx>
 CTO <cto@coompany.xx>
 ------------
 
-Then, you might want a `.mailmap` file looking like:
+Then you might want a `.mailmap` file that looks like:
 ------------
 <cto@company.xx>                       <cto@coompany.xx>
 Some Dude <some@dude.xx>         nick1 <bugs@company.xx>
@@ -72,4 +71,4 @@ Santa Claus <santa.claus@northpole.xx> <me@company.xx>
 ------------
 
 Use hash '#' for comments that are either on their own line, or after
-the email address.
\ No newline at end of file
+the email address.
-- 
1.6.2.1

^ permalink raw reply related

* [PATCH 2/4] Documentation: reworded the "Description" section of git-blame.txt.
From: David J. Mellor @ 2009-03-17  6:16 UTC (permalink / raw)
  To: gitster; +Cc: git
In-Reply-To: <1237270577-17261-1-git-send-email-dmellor@whistlingcat.com>

Reworded this section to make it less chatty. Also made minor grammatical
fixes.

Signed-off-by: David J. Mellor <dmellor@whistlingcat.com>
---
 Documentation/git-bisect.txt |  154 +++++++++++++++++++++---------------------
 1 files changed, 77 insertions(+), 77 deletions(-)

diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index e65c1ca..df0ed36 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -3,7 +3,7 @@ git-bisect(1)
 
 NAME
 ----
-git-bisect - Find the change that introduced a bug by binary search
+git-bisect - Find by binary search the change that introduced a bug
 
 
 SYNOPSIS
@@ -39,7 +39,8 @@ help" or "git bisect -h" to get a long usage description.
 Basic bisect commands: start, bad, good
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The way you use it is:
+Using the Linux kernel tree as an example, basic use of the bisect
+command is as follows:
 
 ------------------------------------------------
 $ git bisect start
@@ -48,61 +49,62 @@ $ git bisect good v2.6.13-rc2    # v2.6.13-rc2 was the last version
                                  # tested that was good
 ------------------------------------------------
 
-When you give at least one bad and one good versions, it will bisect
-the revision tree and say something like:
+When you have specified at least one bad and one good version, the
+command bisects the revision tree and outputs something similar to:
 
 ------------------------------------------------
 Bisecting: 675 revisions left to test after this
 ------------------------------------------------
 
-and check out the state in the middle. Now, compile that kernel, and
-boot it. Now, let's say that this booted kernel works fine, then just
-do
+and then checks out the state in the middle. You would now compile
+that kernel and boot it. If the booted kernel works correctly, you
+would then issue the following command:
 
 ------------------------------------------------
 $ git bisect good			# this one is good
 ------------------------------------------------
 
-which will now say
+which would then output something similar to:
 
 ------------------------------------------------
 Bisecting: 337 revisions left to test after this
 ------------------------------------------------
 
 and you continue along, compiling that one, testing it, and depending
-on whether it is good or bad, you say "git bisect good" or "git bisect
-bad", and ask for the next bisection.
+on whether it is good or bad issuing the command "git bisect good"
+or "git bisect bad" to ask for the next bisection.
 
-Until you have no more left, and you'll have been left with the first
-bad kernel rev in "refs/bisect/bad".
+Eventually there will be no more revisions left to bisect, and you
+will have been left with the first bad kernel revision in "refs/bisect/bad".
 
 Bisect reset
 ~~~~~~~~~~~~
 
-Oh, and then after you want to reset to the original head, do a
+To return to the original head after a bisect session, you issue the
+command:
 
 ------------------------------------------------
 $ git bisect reset
 ------------------------------------------------
 
-to get back to the original branch, instead of being on the bisection
-commit ("git bisect start" will do that for you too, actually: it will
-reset the bisection state).
+This resest the tree to the original branch instead of being on the
+bisection commit ("git bisect start" will also do that, as it resets
+the bisection state).
 
 Bisect visualize
 ~~~~~~~~~~~~~~~~
 
-During the bisection process, you can say
+During the bisection process, you issue the command:
 
 ------------
 $ git bisect visualize
 ------------
 
-to see the currently remaining suspects in 'gitk'.  `visualize` is a bit
-too long to type and `view` is provided as a synonym.
+to see the currently remaining suspects in 'gitk'.  `view` may also
+be used as a synonym for `visualize`.
 
-If 'DISPLAY' environment variable is not set, 'git log' is used
-instead.  You can even give command line options such as `-p` and
+If the 'DISPLAY' environment variable is not set, 'git log' is used
+instead.  You can also give command line options such as `-p` and
 `--stat`.
 
 ------------
@@ -112,57 +114,56 @@ $ git bisect view --stat
 Bisect log and bisect replay
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The good/bad input is logged, and
+The good/bad input is logged, and:
 
 ------------
 $ git bisect log
 ------------
 
 shows what you have done so far. You can truncate its output somewhere
-and save it in a file, and run
+and save it in a file, and run:
 
 ------------
 $ git bisect replay that-file
 ------------
 
-if you find later you made a mistake telling good/bad about a
-revision.
+if you find later that you made a mistake specifying revisions as good/bad.
 
-Avoiding to test a commit
+Avoiding testing a commit
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If in a middle of bisect session, you know what the bisect suggested
-to try next is not a good one to test (e.g. the change the commit
+If in the middle of a bisect session, you know that the next suggested
+revision is not a good one to test (e.g. the change the commit
 introduces is known not to work in your environment and you know it
 does not have anything to do with the bug you are chasing), you may
-want to find a near-by commit and try that instead.
+want to find a nearby commit and try that instead.
 
-It goes something like this:
+For example:
 
 ------------
 $ git bisect good/bad			# previous round was good/bad.
 Bisecting: 337 revisions left to test after this
 $ git bisect visualize			# oops, that is uninteresting.
-$ git reset --hard HEAD~3		# try 3 revs before what
+$ git reset --hard HEAD~3		# try 3 revisions before what
 					# was suggested
 ------------
 
-Then compile and test the one you chose to try. After that, tell
-bisect what the result was as usual.
+Then compile and test the chosen revision. Afterwards the revision
+is marked as good/bad in the usual manner.
 
 Bisect skip
 ~~~~~~~~~~~~
 
-Instead of choosing by yourself a nearby commit, you may just want git
-to do it for you using:
+Instead of choosing by yourself a nearby commit, you can ask git
+to do it for you by issuing the command:
 
 ------------
 $ git bisect skip                 # Current version cannot be tested
 ------------
 
 But computing the commit to test may be slower afterwards and git may
-eventually not be able to tell the first bad among a bad and one or
-more "skip"ped commits.
+eventually not be able to tell the first bad commit among a bad commit
+and one or more skipped commits.
 
 You can even skip a range of commits, instead of just one commit,
 using the "'<commit1>'..'<commit2>'" notation. For example:
@@ -174,30 +175,29 @@ $ git bisect skip v2.5..v2.6
 would mean that no commit between `v2.5` excluded and `v2.6` included
 can be tested.
 
-Note that if you want to also skip the first commit of a range you can
-use something like:
+Note that if you also want to skip the first commit of the range you
+would issue the command:
 
 ------------
 $ git bisect skip v2.5 v2.5..v2.6
 ------------
 
-and the commit pointed to by `v2.5` will be skipped too.
+and the commit pointed to by `v2.5` would also be skipped.
 
 Cutting down bisection by giving more parameters to bisect start
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-You can further cut down the number of trials if you know what part of
-the tree is involved in the problem you are tracking down, by giving
-paths parameters when you say `bisect start`, like this:
+You can further cut down the number of trials, if you know what part of
+the tree is involved in the problem you are tracking down, by specifying
+path parameters when issuing the `bisect start` command, like this:
 
 ------------
 $ git bisect start -- arch/i386 include/asm-i386
 ------------
 
-If you know beforehand more than one good commits, you can narrow the
-bisect space down without doing the whole tree checkout every time you
-give good commits. You give the bad revision immediately after `start`
-and then you give all the good revisions you have:
+If you know beforehand more than one good commit, you can narrow the
+bisect space down by specifying all of the good commits immediately after
+the bad commit when issuing the `bisect start` command:
 
 ------------
 $ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 --
@@ -209,38 +209,38 @@ Bisect run
 ~~~~~~~~~~
 
 If you have a script that can tell if the current source code is good
-or bad, you can automatically bisect using:
+or bad, you can bisect by issuing the command:
 
 ------------
 $ git bisect run my_script arguments
 ------------
 
-Note that the "run" script (`my_script` in the above example) should
-exit with code 0 in case the current source code is good.  Exit with a
+Note that the script (`my_script` in the above example) should
+exit with code 0 if the current source code is good, and exit with a
 code between 1 and 127 (inclusive), except 125, if the current
 source code is bad.
 
-Any other exit code will abort the automatic bisect process. (A
-program that does "exit(-1)" leaves $? = 255, see exit(3) manual page,
-the value is chopped with "& 0377".)
+Any other exit code will abort the bisect process. It should be noted
+that a program that terminates via "exit(-1)" leaves $? = 255, (see the
+exit(3) manual page), as the value is chopped with "& 0377".
 
 The special exit code 125 should be used when the current source code
-cannot be tested. If the "run" script exits with this code, the current
-revision will be skipped, see `git bisect skip` above.
+cannot be tested. If the script exits with this code, the current
+revision will be skipped (see `git bisect skip` above).
 
-You may often find that during bisect you want to have near-constant
-tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
-"revision that does not have this commit needs this patch applied to
-work around other problem this bisection is not interested in")
-applied to the revision being tested.
+You may often find that during a bisect session you want to have
+temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
+header file, or "revision that does not have this commit needs this
+patch applied to work around another problem this bisection is not
+interested in") applied to the revision being tested.
 
 To cope with such a situation, after the inner 'git bisect' finds the
-next revision to test, with the "run" script, you can apply that tweak
-before compiling, run the real test, and after the test decides if the
-revision (possibly with the needed tweaks) passed the test, rewind the
-tree to the pristine state.  Finally the "run" script can exit with
-the status of the real test to let the "git bisect run" command loop to
-determine the outcome.
+next revision to test, the script can apply the patch
+before compiling, run the real test, and afterwards decide if the
+revision (possibly with the needed patch) passed the test and then
+rewind the tree to the pristine state.  Finally the script should exit
+with the status of the real test to let the "git bisect run" command loop
+to determine the eventual outcome of the bisect session.
 
 EXAMPLES
 --------
@@ -264,39 +264,39 @@ $ git bisect run make test           # "make test" builds and tests
 ------------
 $ cat ~/test.sh
 #!/bin/sh
-make || exit 125                   # this "skip"s broken builds
+make || exit 125                   # this skips broken builds
 make test                          # "make test" runs the test suite
 $ git bisect start v1.3 v1.1 --    # v1.3 is bad, v1.1 is good
 $ git bisect run ~/test.sh
 ------------
 +
 Here we use a "test.sh" custom script. In this script, if "make"
-fails, we "skip" the current commit.
+fails, we skip the current commit.
 +
-It's safer to use a custom script outside the repo to prevent
+It is safer to use a custom script outside the repository to prevent
 interactions between the bisect, make and test processes and the
 script.
 +
-And "make test" should "exit 0", if the test suite passes, and
-"exit 1" (for example) otherwise.
+"make test" should "exit 0", if the test suite passes, and
+"exit 1" otherwise.
 
 * Automatically bisect a broken test case:
 +
 ------------
 $ cat ~/test.sh
 #!/bin/sh
-make || exit 125                     # this "skip"s broken builds
+make || exit 125                     # this skips broken builds
 ~/check_test_case.sh                 # does the test case passes ?
 $ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run ~/test.sh
 ------------
 +
-Here "check_test_case.sh" should "exit 0", if the test case passes,
-and "exit 1" (for example) otherwise.
+Here "check_test_case.sh" should "exit 0" if the test case passes,
+and "exit 1" otherwise.
 +
-It's safer if both "test.sh" and "check_test_case.sh" scripts are
-outside the repo to prevent interactions between the bisect, make and
-test processes and the scripts.
+It is safer if both "test.sh" and "check_test_case.sh" scripts are
+outside the repository to prevent interactions between the bisect,
+make and test processes and the scripts.
 
 * Automatically bisect a broken test suite:
 +
-- 
1.6.2.1

^ permalink raw reply related

* [PATCH 4/4] Documentation: minor grammatical fixes in git-branch.txt.
From: David J. Mellor @ 2009-03-17  6:16 UTC (permalink / raw)
  To: gitster; +Cc: git
In-Reply-To: <1237270577-17261-3-git-send-email-dmellor@whistlingcat.com>


Signed-off-by: David J. Mellor <dmellor@whistlingcat.com>
---
 Documentation/git-branch.txt |   50 +++++++++++++++++++++---------------------
 1 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 6103d62..7f7b781 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -18,19 +18,19 @@ SYNOPSIS
 DESCRIPTION
 -----------
 
-With no arguments, existing branches are listed, the current branch will
+With no arguments, existing branches are listed and the current branch will
 be highlighted with an asterisk.  Option `-r` causes the remote-tracking
 branches to be listed, and option `-a` shows both.
 
-With `--contains`, shows only the branches that contains the named commit
-(in other words, the branches whose tip commits are descendant of the
+With `--contains`, shows only the branches that contain the named commit
+(in other words, the branches whose tip commits are descendants of the
 named commit).  With `--merged`, only branches merged into the named
 commit (i.e. the branches whose tip commits are reachable from the named
 commit) will be listed.  With `--no-merged` only branches not merged into
-the named commit will be listed.  Missing <commit> argument defaults to
-'HEAD' (i.e. the tip of the current branch).
+the named commit will be listed.  If the <commit> argument is missing it
+defaults to 'HEAD' (i.e. the tip of the current branch).
 
-In its second form, a new branch named <branchname> will be created.
+In the command's second form, a new branch named <branchname> will be created.
 It will start out with a head equal to the one given as <start-point>.
 If no <start-point> is given, the branch will be created with a head
 equal to that of the currently checked out branch.
@@ -57,9 +57,9 @@ has a reflog then the reflog will also be deleted.
 
 Use -r together with -d to delete remote-tracking branches. Note, that it
 only makes sense to delete remote-tracking branches if they no longer exist
-in remote repository or if 'git-fetch' was configured not to fetch
-them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to
-clean up all obsolete remote-tracking branches.
+in the remote repository or if 'git-fetch' was configured not to fetch
+them again. See also the 'prune' subcommand of linkgit:git-remote[1] for a
+way to clean up all obsolete remote-tracking branches.
 
 
 OPTIONS
@@ -83,7 +83,7 @@ OPTIONS
 	Move/rename a branch and the corresponding reflog.
 
 -M::
-	Move/rename a branch even if the new branchname already exists.
+	Move/rename a branch even if the new branch name already exists.
 
 --color::
 	Color branches to highlight current, local, and remote branches.
@@ -103,17 +103,17 @@ OPTIONS
 	Show sha1 and commit subject line for each head.
 
 --abbrev=<length>::
-	Alter minimum display length for sha1 in output listing,
-	default value is 7.
+	Alter the sha1's minimum display length in the output listing.
+	The default value is 7.
 
 --no-abbrev::
-	Display the full sha1s in output listing rather than abbreviating them.
+	Display the full sha1s in the output listing rather than abbreviating them.
 
 --track::
-	When creating a new branch, set up configuration so that 'git-pull'
+	When creating a new branch, set up the configuration so that 'git-pull'
 	will automatically retrieve data from the start point, which must be
 	a branch. Use this if you always pull from the same upstream branch
-	into the new branch, and if you don't want to use "git pull
+	into the new branch, and if you do not want to use "git pull
 	<repository> <refspec>" explicitly. This behavior is the default
 	when the start point is a remote branch. Set the
 	branch.autosetupmerge configuration variable to `false` if you want
@@ -149,13 +149,13 @@ OPTIONS
 
 <newbranch>::
 	The new name for an existing branch. The same restrictions as for
-	<branchname> applies.
+	<branchname> apply.
 
 
 Examples
 --------
 
-Start development off of a known tag::
+Start development from a known tag::
 +
 ------------
 $ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
@@ -167,7 +167,7 @@ $ git checkout my2.6.14
 <1> This step and the next one could be combined into a single step with
 "checkout -b my2.6.14 v2.6.14".
 
-Delete unneeded branch::
+Delete an unneeded branch::
 +
 ------------
 $ git clone git://git.kernel.org/.../git.git my.git
@@ -176,21 +176,21 @@ $ git branch -d -r origin/todo origin/html origin/man   <1>
 $ git branch -D test                                    <2>
 ------------
 +
-<1> Delete remote-tracking branches "todo", "html", "man". Next 'fetch' or
-'pull' will create them again unless you configure them not to. See
-linkgit:git-fetch[1].
-<2> Delete "test" branch even if the "master" branch (or whichever branch is
-currently checked out) does not have all commits from test branch.
+<1> Delete the remote-tracking branches "todo", "html" and "man". The next
+'fetch' or 'pull' will create them again unless you configure them not to.
+See linkgit:git-fetch[1].
+<2> Delete the "test" branch even if the "master" branch (or whichever branch
+is currently checked out) does not have all commits from the test branch.
 
 
 Notes
 -----
 
-If you are creating a branch that you want to immediately checkout, it's
+If you are creating a branch that you want to checkout immediately, it is
 easier to use the git checkout command with its `-b` option to create
 a branch and check it out with a single command.
 
-The options `--contains`, `--merged` and `--no-merged` serves three related
+The options `--contains`, `--merged` and `--no-merged` serve three related
 but different purposes:
 
 - `--contains <commit>` is used to find all branches which will need
-- 
1.6.2.1

^ permalink raw reply related

* Re: [PATCH][v2] http authentication via prompts (with correct line  lengths)
From: Junio C Hamano @ 2009-03-17  6:27 UTC (permalink / raw)
  To: Amos King; +Cc: git, Daniel Barkalow
In-Reply-To: <d8c371a80903162215k4c27762cva650ea64d7850afa@mail.gmail.com>

Amos King <amos.l.king@gmail.com> writes:

> Junio,
>
> I'm working with Mike on the http auth stuff, and I was testing out
> your patch.  I can get it to work for fetch but push is giving me some
> grief.  Looking through the code I noticed that online 219 of
> http-push.c that http_init is being called with NULL instead of a
> remote.  If I pass in the remote then there is no remotre-url.  I've
> been digging around and can't find where or when that is being set.
> It has been a while since I worked with C but I'd love to jump in and
> help out here.  Can you point me in the right direction to get the
> remote->url[0] set for the http_auth_init to use?

Daniel is the primary culprit who introduced the transport abstraction,
and I think he muttered something about his work-in-progress that involves
in some change in the API.  Perhaps he has some insights here?

Naah.  I forgot that the transport abstraction on the fetch side is much
more integrated but curl_transport_push() simply launches http-push.c that
has a world on its own.  Worse yet, "remote" in http-push.c is not even
the "struct remote"; it is something private to http-push.c called "struct
repo".

I am not sure how much work would be involved in converting (or if it is
even worth to convert) http-push.c to fit better into the transport API,
but if that is feasible, it might be a better longer-term solution.
Right now, builtin-push.c does all the remote inspection and when
http-push is called, the latter gets the information at the lowest level
only; the higher level information such as what nickname was used by the
user to initiate the "git push" process and whether the refspecs came from
the command line or from the config are all lost, which is quite sad.

But as a much lower impact interim solution, I suspect that you can fake a
minimally usable remote.  The http_push() codepath only cares about
remote->http_proxy and remote->url settings as far as I can tell, so
perhaps you can start (with a big warning that the remote you are creating
is a fake one) by filling the absolute minimum?

That is, something along these lines (this comes on top of an obvious
patch that renames existing "remote" variable in http-push. to "repo").

diff --git a/http-push.c b/http-push.c
index dfbb247..f04ac74 100644
--- a/http-push.c
+++ b/http-push.c
@@ -2197,6 +2197,7 @@ int main(int argc, char **argv)
 	int new_refs;
 	struct ref *ref;
 	char *rewritten_url = NULL;
+	struct remote *remote;
 
 	git_extract_argv0_path(argv[0]);
 
@@ -2258,12 +2259,14 @@ int main(int argc, char **argv)
 	if (!repo->url)
 		usage(http_push_usage);
 
+	remote = remote_get(repo->url);
+
 	if (delete_branch && nr_refspec != 1)
 		die("You must specify only one branch name when deleting a remote branch");
 
 	memset(remote_dir_exists, -1, 256);
 
-	http_init(NULL);
+	http_init(remote);
 
 	no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 

^ permalink raw reply related

* Re: [PATCH][v2] http authentication via prompts (with correct line  lengths)
From: Junio C Hamano @ 2009-03-17  6:47 UTC (permalink / raw)
  To: Amos King; +Cc: git, Daniel Barkalow
In-Reply-To: <7v8wn4u0ip.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> That is, something along these lines (this comes on top of an obvious
> patch that renames existing "remote" variable in http-push. to "repo").

And to save you the trouble, here is the "obvious" renaming patch, that
applies on top of 750d930 (http.c: CURLOPT_NETRC_OPTIONAL is not available
in ancient versions of cURL, 2009-03-12).

diff --git a/http-push.c b/http-push.c
index 30d2d34..dfbb247 100644
--- a/http-push.c
+++ b/http-push.c
@@ -97,7 +97,7 @@ struct repo
 	struct remote_lock *locks;
 };
 
-static struct repo *remote;
+static struct repo *repo;
 
 enum transfer_state {
 	NEED_FETCH,
@@ -324,7 +324,7 @@ static void start_fetch_loose(struct transfer_request *request)
 
 	git_SHA1_Init(&request->c);
 
-	url = get_remote_object_url(remote->url, hex, 0);
+	url = get_remote_object_url(repo->url, hex, 0);
 	request->url = xstrdup(url);
 
 	/* If a previous temp file is present, process what was already
@@ -389,7 +389,7 @@ static void start_fetch_loose(struct transfer_request *request)
 	request->state = RUN_FETCH_LOOSE;
 	if (!start_active_slot(slot)) {
 		fprintf(stderr, "Unable to start GET request\n");
-		remote->can_update_info_refs = 0;
+		repo->can_update_info_refs = 0;
 		release_request(request);
 	}
 }
@@ -399,7 +399,7 @@ static void start_mkcol(struct transfer_request *request)
 	char *hex = sha1_to_hex(request->obj->sha1);
 	struct active_request_slot *slot;
 
-	request->url = get_remote_object_url(remote->url, hex, 1);
+	request->url = get_remote_object_url(repo->url, hex, 1);
 
 	slot = get_active_slot();
 	slot->callback_func = process_response;
@@ -434,10 +434,10 @@ static void start_fetch_packed(struct transfer_request *request)
 	struct transfer_request *check_request = request_queue_head;
 	struct active_request_slot *slot;
 
-	target = find_sha1_pack(request->obj->sha1, remote->packs);
+	target = find_sha1_pack(request->obj->sha1, repo->packs);
 	if (!target) {
 		fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
-		remote->can_update_info_refs = 0;
+		repo->can_update_info_refs = 0;
 		release_request(request);
 		return;
 	}
@@ -450,9 +450,9 @@ static void start_fetch_packed(struct transfer_request *request)
 	snprintf(request->tmpfile, sizeof(request->tmpfile),
 		 "%s.temp", filename);
 
-	url = xmalloc(strlen(remote->url) + 64);
+	url = xmalloc(strlen(repo->url) + 64);
 	sprintf(url, "%sobjects/pack/pack-%s.pack",
-		remote->url, sha1_to_hex(target->sha1));
+		repo->url, sha1_to_hex(target->sha1));
 
 	/* Make sure there isn't another open request for this pack */
 	while (check_request) {
@@ -469,7 +469,7 @@ static void start_fetch_packed(struct transfer_request *request)
 	if (!packfile) {
 		fprintf(stderr, "Unable to open local file %s for pack",
 			request->tmpfile);
-		remote->can_update_info_refs = 0;
+		repo->can_update_info_refs = 0;
 		free(url);
 		return;
 	}
@@ -505,7 +505,7 @@ static void start_fetch_packed(struct transfer_request *request)
 	request->state = RUN_FETCH_PACKED;
 	if (!start_active_slot(slot)) {
 		fprintf(stderr, "Unable to start GET request\n");
-		remote->can_update_info_refs = 0;
+		repo->can_update_info_refs = 0;
 		release_request(request);
 	}
 }
@@ -554,10 +554,10 @@ static void start_put(struct transfer_request *request)
 	request->buffer.buf.len = stream.total_out;
 
 	strbuf_addstr(&buf, "Destination: ");
-	append_remote_object_url(&buf, remote->url, hex, 0);
+	append_remote_object_url(&buf, repo->url, hex, 0);
 	request->dest = strbuf_detach(&buf, NULL);
 
-	append_remote_object_url(&buf, remote->url, hex, 0);
+	append_remote_object_url(&buf, repo->url, hex, 0);
 	strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
 	request->url = strbuf_detach(&buf, NULL);
 
@@ -648,7 +648,7 @@ static int refresh_lock(struct remote_lock *lock)
 
 static void check_locks(void)
 {
-	struct remote_lock *lock = remote->locks;
+	struct remote_lock *lock = repo->locks;
 	time_t current_time = time(NULL);
 	int time_remaining;
 
@@ -788,7 +788,7 @@ static void finish_request(struct transfer_request *request)
 		if (request->curl_result != CURLE_OK) {
 			fprintf(stderr, "Unable to get pack file %s\n%s",
 				request->url, curl_errorstr);
-			remote->can_update_info_refs = 0;
+			repo->can_update_info_refs = 0;
 		} else {
 			off_t pack_size = ftell(request->local_stream);
 
@@ -798,7 +798,7 @@ static void finish_request(struct transfer_request *request)
 					       request->filename)) {
 				target = (struct packed_git *)request->userData;
 				target->pack_size = pack_size;
-				lst = &remote->packs;
+				lst = &repo->packs;
 				while (*lst != target)
 					lst = &((*lst)->next);
 				*lst = (*lst)->next;
@@ -806,7 +806,7 @@ static void finish_request(struct transfer_request *request)
 				if (!verify_pack(target))
 					install_packed_git(target);
 				else
-					remote->can_update_info_refs = 0;
+					repo->can_update_info_refs = 0;
 			}
 		}
 		release_request(request);
@@ -889,7 +889,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
 		get_remote_object_list(obj->sha1[0]);
 	if (obj->flags & (REMOTE | PUSHING))
 		return 0;
-	target = find_sha1_pack(obj->sha1, remote->packs);
+	target = find_sha1_pack(obj->sha1, repo->packs);
 	if (target) {
 		obj->flags |= REMOTE;
 		return 0;
@@ -930,8 +930,8 @@ static int fetch_index(unsigned char *sha1)
 	struct slot_results results;
 
 	/* Don't use the index if the pack isn't there */
-	url = xmalloc(strlen(remote->url) + 64);
-	sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
+	url = xmalloc(strlen(repo->url) + 64);
+	sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
 	slot = get_active_slot();
 	slot->results = &results;
 	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -956,7 +956,7 @@ static int fetch_index(unsigned char *sha1)
 	if (push_verbosely)
 		fprintf(stderr, "Getting index for pack %s\n", hex);
 
-	sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
+	sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
 
 	filename = sha1_pack_index_name(sha1);
 	snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
@@ -1018,8 +1018,8 @@ static int setup_index(unsigned char *sha1)
 		return -1;
 
 	new_pack = parse_pack_index(sha1);
-	new_pack->next = remote->packs;
-	remote->packs = new_pack;
+	new_pack->next = repo->packs;
+	repo->packs = new_pack;
 	return 0;
 }
 
@@ -1037,8 +1037,8 @@ static int fetch_indices(void)
 	if (push_verbosely)
 		fprintf(stderr, "Getting pack list\n");
 
-	url = xmalloc(strlen(remote->url) + 20);
-	sprintf(url, "%sobjects/info/packs", remote->url);
+	url = xmalloc(strlen(repo->url) + 20);
+	sprintf(url, "%sobjects/info/packs", repo->url);
 
 	slot = get_active_slot();
 	slot->results = &results;
@@ -1223,11 +1223,11 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
 	struct curl_slist *dav_headers = NULL;
 	struct xml_ctx ctx;
 
-	url = xmalloc(strlen(remote->url) + strlen(path) + 1);
-	sprintf(url, "%s%s", remote->url, path);
+	url = xmalloc(strlen(repo->url) + strlen(path) + 1);
+	sprintf(url, "%s%s", repo->url, path);
 
 	/* Make sure leading directories exist for the remote ref */
-	ep = strchr(url + strlen(remote->url) + 1, '/');
+	ep = strchr(url + strlen(repo->url) + 1, '/');
 	while (ep) {
 		char saved_character = ep[1];
 		ep[1] = '\0';
@@ -1319,8 +1319,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
 	} else {
 		lock->url = url;
 		lock->start_time = time(NULL);
-		lock->next = remote->locks;
-		remote->locks = lock;
+		lock->next = repo->locks;
+		repo->locks = lock;
 	}
 
 	return lock;
@@ -1330,7 +1330,7 @@ static int unlock_remote(struct remote_lock *lock)
 {
 	struct active_request_slot *slot;
 	struct slot_results results;
-	struct remote_lock *prev = remote->locks;
+	struct remote_lock *prev = repo->locks;
 	struct curl_slist *dav_headers;
 	int rc = 0;
 
@@ -1356,8 +1356,8 @@ static int unlock_remote(struct remote_lock *lock)
 
 	curl_slist_free_all(dav_headers);
 
-	if (remote->locks == lock) {
-		remote->locks = lock->next;
+	if (repo->locks == lock) {
+		repo->locks = lock->next;
 	} else {
 		while (prev && prev->next != lock)
 			prev = prev->next;
@@ -1375,7 +1375,7 @@ static int unlock_remote(struct remote_lock *lock)
 
 static void remove_locks(void)
 {
-	struct remote_lock *lock = remote->locks;
+	struct remote_lock *lock = repo->locks;
 
 	fprintf(stderr, "Removing remote locks...\n");
 	while (lock) {
@@ -1457,7 +1457,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
 				}
 			}
 			if (path) {
-				path += remote->path_len;
+				path += repo->path_len;
 				ls->dentry_name = xstrdup(path);
 			}
 		} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
@@ -1480,7 +1480,7 @@ static void remote_ls(const char *path, int flags,
 		      void (*userFunc)(struct remote_ls_ctx *ls),
 		      void *userData)
 {
-	char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
+	char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
 	struct active_request_slot *slot;
 	struct slot_results results;
 	struct strbuf in_buffer = STRBUF_INIT;
@@ -1496,7 +1496,7 @@ static void remote_ls(const char *path, int flags,
 	ls.userData = userData;
 	ls.userFunc = userFunc;
 
-	sprintf(url, "%s%s", remote->url, path);
+	sprintf(url, "%s%s", repo->url, path);
 
 	strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
 
@@ -1574,7 +1574,7 @@ static int locking_available(void)
 	struct xml_ctx ctx;
 	int lock_flags = 0;
 
-	strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
+	strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, repo->url);
 
 	dav_headers = curl_slist_append(dav_headers, "Depth: 0");
 	dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
@@ -1586,7 +1586,7 @@ static int locking_available(void)
 	curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
+	curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
 	curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
 	curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
@@ -1617,15 +1617,15 @@ static int locking_available(void)
 			XML_ParserFree(parser);
 			if (!lock_flags)
 				error("Error: no DAV locking support on %s",
-				      remote->url);
+				      repo->url);
 
 		} else {
 			error("Cannot access URL %s, return code %d",
-			      remote->url, results.curl_result);
+			      repo->url, results.curl_result);
 			lock_flags = 0;
 		}
 	} else {
-		error("Unable to start PROPFIND request on %s", remote->url);
+		error("Unable to start PROPFIND request on %s", repo->url);
 	}
 
 	strbuf_release(&out_buffer.buf);
@@ -1814,10 +1814,10 @@ static void one_remote_ref(char *refname)
 
 	ref = alloc_ref(refname);
 
-	if (http_fetch_ref(remote->url, ref) != 0) {
+	if (http_fetch_ref(repo->url, ref) != 0) {
 		fprintf(stderr,
 			"Unable to fetch ref %s from %s\n",
-			refname, remote->url);
+			refname, repo->url);
 		free(ref);
 		return;
 	}
@@ -1826,7 +1826,7 @@ static void one_remote_ref(char *refname)
 	 * Fetch a copy of the object if it doesn't exist locally - it
 	 * may be required for updating server info later.
 	 */
-	if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
+	if (repo->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
 		obj = lookup_unknown_object(ref->old_sha1);
 		if (obj) {
 			fprintf(stderr,	"  fetch %s for %s\n",
@@ -1921,10 +1921,10 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
 
 	ref = alloc_ref(ls->dentry_name);
 
-	if (http_fetch_ref(remote->url, ref) != 0) {
+	if (http_fetch_ref(repo->url, ref) != 0) {
 		fprintf(stderr,
 			"Unable to fetch ref %s from %s\n",
-			ls->dentry_name, remote->url);
+			ls->dentry_name, repo->url);
 		aborted = 1;
 		free(ref);
 		return;
@@ -1999,12 +1999,12 @@ static void update_remote_info_refs(struct remote_lock *lock)
 
 static int remote_exists(const char *path)
 {
-	char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
+	char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
 	struct active_request_slot *slot;
 	struct slot_results results;
 	int ret = -1;
 
-	sprintf(url, "%s%s", remote->url, path);
+	sprintf(url, "%s%s", repo->url, path);
 
 	slot = get_active_slot();
 	slot->results = &results;
@@ -2034,8 +2034,8 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
 	struct active_request_slot *slot;
 	struct slot_results results;
 
-	url = xmalloc(strlen(remote->url) + strlen(path) + 1);
-	sprintf(url, "%s%s", remote->url, path);
+	url = xmalloc(strlen(repo->url) + strlen(path) + 1);
+	sprintf(url, "%s%s", repo->url, path);
 
 	slot = get_active_slot();
 	slot->results = &results;
@@ -2150,7 +2150,7 @@ static int delete_remote_branch(char *pattern, int force)
 				     "of your current HEAD.\n"
 				     "If you are sure you want to delete it,"
 				     " run:\n\t'git http-push -D %s %s'",
-				     remote_ref->name, remote->url, pattern);
+				     remote_ref->name, repo->url, pattern);
 		}
 	}
 
@@ -2158,8 +2158,8 @@ static int delete_remote_branch(char *pattern, int force)
 	fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
 	if (dry_run)
 		return 0;
-	url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1);
-	sprintf(url, "%s%s", remote->url, remote_ref->name);
+	url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1);
+	sprintf(url, "%s%s", repo->url, remote_ref->name);
 	slot = get_active_slot();
 	slot->results = &results;
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@ -2202,7 +2202,7 @@ int main(int argc, char **argv)
 
 	setup_git_directory();
 
-	remote = xcalloc(sizeof(*remote), 1);
+	repo = xcalloc(sizeof(*repo), 1);
 
 	argv++;
 	for (i = 1; i < argc; i++, argv++) {
@@ -2235,14 +2235,14 @@ int main(int argc, char **argv)
 				continue;
 			}
 		}
-		if (!remote->url) {
+		if (!repo->url) {
 			char *path = strstr(arg, "//");
-			remote->url = arg;
-			remote->path_len = strlen(arg);
+			repo->url = arg;
+			repo->path_len = strlen(arg);
 			if (path) {
-				remote->path = strchr(path+2, '/');
-				if (remote->path)
-					remote->path_len = strlen(remote->path);
+				repo->path = strchr(path+2, '/');
+				if (repo->path)
+					repo->path_len = strlen(repo->path);
 			}
 			continue;
 		}
@@ -2255,7 +2255,7 @@ int main(int argc, char **argv)
 	die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
 #endif
 
-	if (!remote->url)
+	if (!repo->url)
 		usage(http_push_usage);
 
 	if (delete_branch && nr_refspec != 1)
@@ -2267,13 +2267,13 @@ int main(int argc, char **argv)
 
 	no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 
-	if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
-		rewritten_url = xmalloc(strlen(remote->url)+2);
-		strcpy(rewritten_url, remote->url);
+	if (repo->url && repo->url[strlen(repo->url)-1] != '/') {
+		rewritten_url = xmalloc(strlen(repo->url)+2);
+		strcpy(rewritten_url, repo->url);
 		strcat(rewritten_url, "/");
-		remote->path = rewritten_url + (remote->path - remote->url);
-		remote->path_len++;
-		remote->url = rewritten_url;
+		repo->path = rewritten_url + (repo->path - repo->url);
+		repo->path_len++;
+		repo->url = rewritten_url;
 	}
 
 	/* Verify DAV compliance/lock support */
@@ -2285,20 +2285,20 @@ int main(int argc, char **argv)
 	sigchain_push_common(remove_locks_on_signal);
 
 	/* Check whether the remote has server info files */
-	remote->can_update_info_refs = 0;
-	remote->has_info_refs = remote_exists("info/refs");
-	remote->has_info_packs = remote_exists("objects/info/packs");
-	if (remote->has_info_refs) {
+	repo->can_update_info_refs = 0;
+	repo->has_info_refs = remote_exists("info/refs");
+	repo->has_info_packs = remote_exists("objects/info/packs");
+	if (repo->has_info_refs) {
 		info_ref_lock = lock_remote("info/refs", LOCK_TIME);
 		if (info_ref_lock)
-			remote->can_update_info_refs = 1;
+			repo->can_update_info_refs = 1;
 		else {
 			fprintf(stderr, "Error: cannot lock existing info/refs\n");
 			rc = 1;
 			goto cleanup;
 		}
 	}
-	if (remote->has_info_packs)
+	if (repo->has_info_packs)
 		fetch_indices();
 
 	/* Get a list of all local and remote heads to validate refspecs */
@@ -2456,8 +2456,8 @@ int main(int argc, char **argv)
 	}
 
 	/* Update remote server info if appropriate */
-	if (remote->has_info_refs && new_refs) {
-		if (info_ref_lock && remote->can_update_info_refs) {
+	if (repo->has_info_refs && new_refs) {
+		if (info_ref_lock && repo->can_update_info_refs) {
 			fprintf(stderr, "Updating remote server info\n");
 			if (!dry_run)
 				update_remote_info_refs(info_ref_lock);
@@ -2470,7 +2470,7 @@ int main(int argc, char **argv)
 	free(rewritten_url);
 	if (info_ref_lock)
 		unlock_remote(info_ref_lock);
-	free(remote);
+	free(repo);
 
 	curl_slist_free_all(no_pragma_header);
 

^ permalink raw reply related

* Re: [StGit PATCH 1/5] Check for local changes with "goto"
From: Karl Hasselström @ 2009-03-17  7:06 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0903160756g79ac3464i4bb6f7f61ba0555a@mail.gmail.com>

On 2009-03-16 14:56:11 +0000, Catalin Marinas wrote:

> 2009/3/13 Karl Hasselström <kha@treskal.com>:
>
> > "Repository" is misleading here. Maybe something like
> >
> >   ix_c = iw.index.is_clean(self.stack.head)
> >   wt_c = iw.worktree_clean()
> >   if not ix_c or not wt_c:
> >       self.__halt('%s not clean. Use "refresh" or "status --reset"'
> >                   % { (False, True): 'Index', (True, False): 'Worktree',
> >                       (False, False): 'Index and worktree' }[(ix_c, wt_c)])
>
> I added two separate if's as I don't find the above readable :-)
>
> if not iw.worktree_clean():
>     self.__halt('Worktree not clean. Use "refresh" or "status --reset"')
> if not iw.index.is_clean(self.stack.head):
>     self.__halt('Index not clean. Use "refresh" or "status --reset"')

It's actually quite nice once you get used to the idea of ephemeral
dictionaries just for selection inside an expression ... :-)

Your version doesn't generate the "Your index and worktree are both
dirty" warning, but I guess that's OK.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply

* Re: undoing something
From: Junio C Hamano @ 2009-03-17  7:09 UTC (permalink / raw)
  To: Nanako Shiraishi; +Cc: John Dlugosz, git, Paolo Bonzini, Jay Soffian
In-Reply-To: <20090317064519.6117@nanako3.lavabit.com>

Nanako Shiraishi <nanako3@lavabit.com> writes:

> Quoting John Dlugosz <JDlugosz@TradeStation.com>:
>
>> === Re: ===
>>  (2) if you are not, you can obviously check out topic and do the above,
>>      or "git branch -f topic topic^".
>> === end ===
>>
>> As documented, this destroys the existing branch and makes a new one.
>> That would, by design, blow away the reflog for that branch.
>
> Does it?  If so I think you have an incorrect documentation.
>
> $ rm -fr /tmp/gomi && mkdir /tmp/gomi
> $ cd /tmp/gomi
> $ git init
> $ echo hello >world
> $ git add world
> $ git commit -m initial
> $ seq 1 100 | while read num; do echo $num >world; git commit -a -m $num; done
> $ git checkout -b side master~60
> $ git branch -f master master@{20}
> $ git log --oneline -g master | head -n 10
> 0acf8c1 master@{0}: branch: Reset from master@{20}
> 945c3ee master@{1}: commit: 100
> 54fcb36 master@{2}: commit: 99
> b314a1e master@{3}: commit: 98
> e91d999 master@{4}: commit: 97
> 0d88853 master@{5}: commit: 96
> 0124315 master@{6}: commit: 95
> 5df2cc5 master@{7}: commit: 94
> ...
> 0813a46 master@{9}: commit: 92

I didn't even notice there was another question buried.  Thanks.

Documentation/git-branch.txt says this:

        -f::
                Force the creation of a new branch even if it means deleting
                a branch that already exists with the same name.

which does imply that it first destroys the branch altogether and
recreates as if there was no such branch.

But that is actually not what the code does to reflog, and I think the
behaviour makes a lot more sense than "destroy and create" the
documentation implies.  branch.c::create_branch() has this:

	if (forcing)
		snprintf(msg, sizeof msg, "branch: Reset from %s",
			 start_name);
	else
		snprintf(msg, sizeof msg, "branch: Created from %s",
			 start_name);

The message for your master@{0} example came from the "forcing" codepath.

The documentation is indeed wrong.  It is more like "create a new branch,
or if the named branch already exists, reset the tip of it".  If we want
to sound alarmist, we could add "even if it means making the existing
history unreachable from the new tip of the branch", but I think "reset"
already means that and it would be redundant.

The create_branch() function does another thing, though.  It sets up the
tracking information _if asked_.  Because one branch cannot track more
than one "other things" at once, it inevitably overwrites the previous
tracking information if you say "branch --track -f dev origin/dev" if dev
were tracking something else.  But if you do not let it set up tracking,
the old tracking configuration is _not_ discarded.  I am not sure if that
was intended (the branch.<name>.remote nor branch.<name>.merge variables
are not something I use myself), but it makes sort of sense.  If you do
"git branch -f dev dev~2" to rewind its tip, you do not want to lose its
tracking information, so the current behaviour makes sense in that
respect.

I am not sure about how branch.autsetupmerge does interact with this in
the current code, nor how it should interact with it in the ideal world,
though.  That's for interested parties (I suspect Jay and Paolo?) to
figure out.

^ permalink raw reply

* Re: [StGit PATCH 3/5] Add automatic git-mergetool invocation to the new infrastructure
From: Karl Hasselström @ 2009-03-17  7:12 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0903160803y25eb3f45y96d68e734b22e5f9@mail.gmail.com>

On 2009-03-16 15:03:09 +0000, Catalin Marinas wrote:

> 2009/3/13 Karl Hasselström <kha@treskal.com>:
>
> > On 2009-03-12 12:09:07 +0000, Catalin Marinas wrote:
> >
> > >                  # There were conflicts
> > > -                conflicts = [l for l in output if l.startswith('CONFLICT')]
> > > -                raise MergeConflictException(conflicts)
> > > +                if interactive:
> > > +                    self.mergetool()
> > > +                else:
> > > +                    conflicts = [l for l in output if l.startswith('CONFLICT')]
> > > +                    raise MergeConflictException(conflicts)
> >
> > Does the merge tool always resolve all conflicts? If it doesn't,
> > the two lines in the "else" branch should probably be run
> > unconditionally.
> [...]
> > > +        # check for unmerged entries (prepend 'CONFLICT ' for consistency with
> > > +        # merge())
> > > +        conflicts = ['CONFLICT ' + f for f in self.index.conflicts()]
> > > +        if conflicts:
> > > +            raise MergeConflictException(conflicts)
> > > +        elif err:
> > > +            raise MergeException('"git mergetool" failed, exit code: %d' % err)
> >
> > Ah, you take care of conflicts here too. Hmm. I guess that's fine
> > too, though there is some code duplication. Maybe a helper
> > function that takes output as a parameter, and raises
> > MergeConflictException if necessary?
>
> The non-interactive path assumes that there are conflicts if "git
> merge-recursive" returned an error and it simply splits the output
> if this command. The mergetool path has to run "git ls-files
> --unmerged" to check if there were any left conflicts. I wouldn't
> call "git ls-files" in the first case as we already have the
> information.

I was thinking of a function you'd call with either the output of the
merge operation or ls-files depending on the code path. But maybe it's
not worth it.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply

* Re: [StGit PATCH 5/5] Convert "float" to the lib infrastructure
From: Karl Hasselström @ 2009-03-17  7:16 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0903160936m1971fbaft928a495eaab4fa20@mail.gmail.com>

On 2009-03-16 16:36:43 +0000, Catalin Marinas wrote:

> 2009/3/13 Karl Hasselström <kha@treskal.com>:
>
> > On 2009-03-12 12:09:18 +0000, Catalin Marinas wrote:
> >
> > >  options = [
> > >      opt('-s', '--series', action = 'store_true',
> > > -        short = 'Rearrange according to a series file')]
> > > +        short = 'Rearrange according to a series file')
> > > +    ] + argparse.keep_option()
> >
> > This flag should take the filename as a parameter, both because
> > it's the right thing to do and because it'll make the tab
> > completion work right (as is, it'll complete on patch names after
> > the -s flag).
> >
> > Something like
> >
> >  opt('-s', '--series', type = 'string')
> >
> > ought to do it.
>
> This command was accepting series via the stdin as well (maybe for
> easier use in other scripts or from stgit.el).

Ah. Hmm, I'd prefer if it used "-" for that, for consistency. And
because I don't know how to make flags with optional parameters. :-/

> Anyway, it doesn't seem to make any difference with the bash
> completion. It still tries to complete patches but when this fails
> bash lists files if the prefix matches some.

Hmm, that's not right. But I can have a look at it if you like.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply

* [PATCH 1/2] MinGW: a helper function that translates Win32 API error codes
From: Johannes Sixt @ 2009-03-17  7:39 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Johannes Schindelin, Petr Kodl

From: Petr Kodl <petrkodl@gmail.com>
Date: Sat, 24 Jan 2009 15:04:39 +0100

This function translates many possible Win32 error codes to suitable
errno numbers.  We will use it in our wrapper functions that need to call
into Win32.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
  Dscho,

  I've split this off from the Petr's hard-link patch and moved the function
  to the top or mingw.c because we should reuse it in our other wrappers
  to convert error codes.

  -- Hannes

  compat/mingw.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 27bcf3f..f66ad56 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -4,6 +4,119 @@

  unsigned int _CRT_fmode = _O_BINARY;

+static int err_win_to_posix(DWORD winerr)
+{
+	int error = ENOSYS;
+	switch(winerr) {
+	case ERROR_ACCESS_DENIED: error = EACCES; break;
+	case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
+	case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
+	case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
+	case ERROR_ALREADY_EXISTS: error = EEXIST; break;
+	case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
+	case ERROR_BAD_COMMAND: error = EIO; break;
+	case ERROR_BAD_DEVICE: error = ENODEV; break;
+	case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
+	case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
+	case ERROR_BAD_FORMAT: error = ENOEXEC; break;
+	case ERROR_BAD_LENGTH: error = EINVAL; break;
+	case ERROR_BAD_PATHNAME: error = ENOENT; break;
+	case ERROR_BAD_PIPE: error = EPIPE; break;
+	case ERROR_BAD_UNIT: error = ENODEV; break;
+	case ERROR_BAD_USERNAME: error = EINVAL; break;
+	case ERROR_BROKEN_PIPE: error = EPIPE; break;
+	case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
+	case ERROR_BUSY: error = EBUSY; break;
+	case ERROR_BUSY_DRIVE: error = EBUSY; break;
+	case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
+	case ERROR_CANNOT_MAKE: error = EACCES; break;
+	case ERROR_CANTOPEN: error = EIO; break;
+	case ERROR_CANTREAD: error = EIO; break;
+	case ERROR_CANTWRITE: error = EIO; break;
+	case ERROR_CRC: error = EIO; break;
+	case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
+	case ERROR_DEVICE_IN_USE: error = EBUSY; break;
+	case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
+	case ERROR_DIRECTORY: error = EINVAL; break;
+	case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
+	case ERROR_DISK_CHANGE: error = EIO; break;
+	case ERROR_DISK_FULL: error = ENOSPC; break;
+	case ERROR_DRIVE_LOCKED: error = EBUSY; break;
+	case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
+	case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
+	case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
+	case ERROR_FILE_EXISTS: error = EEXIST; break;
+	case ERROR_FILE_INVALID: error = ENODEV; break;
+	case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
+	case ERROR_GEN_FAILURE: error = EIO; break;
+	case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
+	case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
+	case ERROR_INVALID_ACCESS: error = EACCES; break;
+	case ERROR_INVALID_ADDRESS: error = EFAULT; break;
+	case ERROR_INVALID_BLOCK: error = EFAULT; break;
+	case ERROR_INVALID_DATA: error = EINVAL; break;
+	case ERROR_INVALID_DRIVE: error = ENODEV; break;
+	case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
+	case ERROR_INVALID_FLAGS: error = EINVAL; break;
+	case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
+	case ERROR_INVALID_HANDLE: error = EBADF; break;
+	case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
+	case ERROR_INVALID_NAME: error = EINVAL; break;
+	case ERROR_INVALID_OWNER: error = EINVAL; break;
+	case ERROR_INVALID_PARAMETER: error = EINVAL; break;
+	case ERROR_INVALID_PASSWORD: error = EPERM; break;
+	case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
+	case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
+	case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
+	case ERROR_INVALID_WORKSTATION: error = EACCES; break;
+	case ERROR_IO_DEVICE: error = EIO; break;
+	case ERROR_IO_INCOMPLETE: error = EINTR; break;
+	case ERROR_LOCKED: error = EBUSY; break;
+	case ERROR_LOCK_VIOLATION: error = EACCES; break;
+	case ERROR_LOGON_FAILURE: error = EACCES; break;
+	case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
+	case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
+	case ERROR_MORE_DATA: error = EPIPE; break;
+	case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
+	case ERROR_NOACCESS: error = EFAULT; break;
+	case ERROR_NONE_MAPPED: error = EINVAL; break;
+	case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
+	case ERROR_NOT_READY: error = EAGAIN; break;
+	case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
+	case ERROR_NO_DATA: error = EPIPE; break;
+	case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
+	case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
+	case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
+	case ERROR_OPEN_FAILED: error = EIO; break;
+	case ERROR_OPEN_FILES: error = EBUSY; break;
+	case ERROR_OPERATION_ABORTED: error = EINTR; break;
+	case ERROR_OUTOFMEMORY: error = ENOMEM; break;
+	case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
+	case ERROR_PATH_BUSY: error = EBUSY; break;
+	case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
+	case ERROR_PIPE_BUSY: error = EBUSY; break;
+	case ERROR_PIPE_CONNECTED: error = EPIPE; break;
+	case ERROR_PIPE_LISTENING: error = EPIPE; break;
+	case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
+	case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
+	case ERROR_READ_FAULT: error = EIO; break;
+	case ERROR_SEEK: error = EIO; break;
+	case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
+	case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
+	case ERROR_SHARING_VIOLATION: error = EACCES; break;
+	case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
+	case ERROR_SWAPERROR: error = ENOENT; break;
+	case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
+	case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
+	case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
+	case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
+	case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
+	case ERROR_WRITE_FAULT: error = EIO; break;
+	case ERROR_WRITE_PROTECT: error = EROFS; break;
+	}
+	return error;
+}
+
  #undef open
  int mingw_open (const char *filename, int oflags, ...)
  {
-- 
1.6.2.rc2.971.g14d5

^ permalink raw reply related

* Re: Transparently encrypt repository contents with GPG
From: Jeff King @ 2009-03-17  7:40 UTC (permalink / raw)
  To: Michael J Gruber
  Cc: Junio C Hamano, Sverre Rabbelier, Thomas Rast, Matthias Nothhaft,
	git
In-Reply-To: <49BE77DD.5020407@drmicha.warpmail.net>

On Mon, Mar 16, 2009 at 05:01:33PM +0100, Michael J Gruber wrote:

> Now, a simple test shows that git diff obviously does this when diffing
> HEAD to worktree:
> 
> diff between HEAD and clean(worktree)
> 
> Which is the right thing. It just seems so that textconv is not even
> called "in the wrong place of the chain", but messes the diff up in this
> way:
> 
> diff between textconv(HEAD) and textconv(worktree)
> 
> (I expected clean(textconv(worktree)) first, which would be wrong, too).
> I.e., the clean filter is ignored completely in the presence of textconv.

Yeah, I think this should probably be textconv(clean(worktree)) to match
the regular HEAD/worktree diff (if it isn't already). Can you put
together a test that shows the breakage?

-Peff

^ permalink raw reply

* Re: [PATCH] git-push.txt: describe how to default to pushing only current branch
From: Jeff King @ 2009-03-17  7:46 UTC (permalink / raw)
  To: Chris Johnsen; +Cc: git, Junio C Hamano
In-Reply-To: <1237085349-14824-1-git-send-email-chris_johnsen@pobox.com>

On Sat, Mar 14, 2009 at 09:49:09PM -0500, Chris Johnsen wrote:

> 1) literals that contain a double quote
> 
> 	$ git grep '`[^`]*"[^`]`' | cat
> 	config.txt:You can have `[section]` if you have `[section "subsection"]`, but you
> 
>    There might be a better regexp to find these, I did not think
>    about it too long. The above "hit" seems like a reasonable
>    literal string. Maybe it is OK to live with this one
>    ("[section "subsection"]").

Hmm, good point. Something with typeface that could not be in the string
contents would probably be a better choice. The linkgit: links appear
bolded. We could do that. We could also try underlining, though that
might be hard to read if any strings contained underscores.

I tried to find examples of other manpages that faced the same problem.
I would guess that bold is the best bet (for example, the 'cat' manpage
on my system looks like (excuse my fake markup):

  -A, --show-all
      equivalent to <b>-vET</b>

> 2) manpage-1.72.xsl 
> 
>    I have been setting DOCBOOK_XSL_172 to avoid the ".ft" problem
>    (<http://article.gmane.org/gmane.comp.version-control.git/112943>;
>    my system is Mac OS X 10.4.11 with MacPorts asciidoc 8.3.1,
>    xmlto version 0.0.21, and docbook-xsl 1.74.0). Since non-null
>    DOCBOOK_XSL_172 replaces callouts.xsl with manpage-1.72.xsl, I
>    added the line to manpage-1.72.xsl.

The "callouts" XSL is obviously becoming more than that (there is
already a "I know, this is not a callout, but where else to put it?"
comment in it). It probably makes sense to rename it to manpage.xsl (or
even manpage-1.8.xsl), factor out common parts to manpage-base.xsl, and
then include the -base version from both manpage and manpage-1.72.xsl.

Want to do a patch?

-Peff

^ permalink raw reply

* [PATCH 2/2] MinGW: a hardlink implementation
From: Johannes Sixt @ 2009-03-17  7:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Johannes Schindelin, Petr Kodl
In-Reply-To: <49BF53C2.6020707@kdbg.org>

From: Petr Kodl <petrkodl@gmail.com>
Date: Sat, 24 Jan 2009 15:04:39 +0100

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
  This is the meat of Petr's original patch with the fixup that was
  discussed in the msysgit mailing list (WINAPI was added in the
  typedef).

  -- Hannes

  compat/mingw.c |   21 +++++++++++++++++++++
  compat/mingw.h |    3 +--
  2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index f66ad56..171fa85 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1118,3 +1118,24 @@ void mingw_open_html(const char *unixpath)
  	printf("Launching default browser to display HTML ...\n");
  	ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
  }
+
+int link(const char *oldpath, const char *newpath)
+{
+	typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
+	static T create_hard_link = NULL;
+	if (!create_hard_link) {
+		create_hard_link = (T) GetProcAddress(
+			GetModuleHandle("kernel32.dll"), "CreateHardLinkA");
+		if (!create_hard_link)
+			create_hard_link = (T)-1;
+	}
+	if (create_hard_link == (T)-1) {
+		errno = ENOSYS;
+		return -1;
+	}
+	if (!create_hard_link(newpath, oldpath, NULL)) {
+		errno = err_win_to_posix(GetLastError());
+		return -1;
+	}
+	return 0;
+}
diff --git a/compat/mingw.h b/compat/mingw.h
index f5da647..762eb14 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -67,8 +67,6 @@ static inline int readlink(const char *path, char *buf, size_t bufsiz)
  { errno = ENOSYS; return -1; }
  static inline int symlink(const char *oldpath, const char *newpath)
  { errno = ENOSYS; return -1; }
-static inline int link(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 int fork(void)
@@ -134,6 +132,7 @@ int getpagesize(void);	/* defined in MinGW's libgcc.a */
  struct passwd *getpwuid(int uid);
  int setitimer(int type, struct itimerval *in, struct itimerval *out);
  int sigaction(int sig, struct sigaction *in, struct sigaction *out);
+int link(const char *oldpath, const char *newpath);

  /*
   * replacements of existing functions
-- 
1.6.2.rc2.971.g14d5

^ permalink raw reply related

* Re: What's cooking in git.git (Mar 2009, #01; Tue, 03)
From: Jeff King @ 2009-03-17  7:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vprgiysow.fsf@gitster.siamese.dyndns.org>

On Sun, Mar 15, 2009 at 09:53:19PM -0700, Junio C Hamano wrote:

> But in reality, contributors who had leftover topics on 'next' simply
> stopped working on their topics on 'next' without spending the freed up
> time on concentrating on 'master'.  In an ideal world, the choice would be
> between "git time on 'next'" vs "git time on 'master'", and closing 'next'
> was meant to force the choice, but instead the outcome became "less git
> time until 'next' reopens".

I think that is a reasonable argument for keeping 'next' open, and it
seems to be borne out by this experiment (the post-1.6.2 period seemed
no better or worse for bugfixes to me).

Now the only problem with keeping next open is that the maintainer
misses out on the relative lull in activity during release freeze to
catch up on his day job work. But if you can handle that, I'm certainly
in no position to complain. :)

-Peff

^ permalink raw reply


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