Merge branch 'stable-4.3' into stable-4.4

* stable-4.3:
  Fix computation of id in WorkingTreeIterator with autocrlf and
    smudging
  Prepare 4.3.2-SNAPSHOT builds
  JGit v4.3.1.201605051710-r
  Scan loose ref before packed in case gc about to remove the loose
  Fix possible NPEs when reporting transport errors
  Fix calling of clean/smudge filters from Checkout,MergeCommands
  Fix ApplyCommand when result of patch is an empty file

Change-Id: I829f06699f6670e519d04c927bdba4b82df29199
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W.patch
new file mode 100644
index 0000000..cfecb8c
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W.patch
@@ -0,0 +1,7 @@
+diff --git a/W b/W
+index a3648a1..2d44096 100644
+--- a/W
++++ b/W
+@@ -1 +0,0 @@
+-a
+\ No newline at end of file
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W_PostImage
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W_PostImage
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W_PreImage
new file mode 100644
index 0000000..2e65efe
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/W_PreImage
@@ -0,0 +1 @@
+a
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
index 239c844..f2b5b3b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
@@ -147,6 +147,16 @@ public void testModifyE() throws Exception {
 	}
 
 	@Test
+	public void testModifyW() throws Exception {
+		ApplyResult result = init("W");
+		assertEquals(1, result.getUpdatedFiles().size());
+		assertEquals(new File(db.getWorkTree(), "W"),
+				result.getUpdatedFiles().get(0));
+		checkFile(new File(db.getWorkTree(), "W"),
+				b.getString(0, b.size(), false));
+	}
+
+	@Test
 	public void testModifyX() throws Exception {
 		ApplyResult result = init("X");
 		assertEquals(1, result.getUpdatedFiles().size());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
index 8162ac4..0bb6610 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
@@ -88,7 +88,6 @@
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.util.FileUtils;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class CheckoutCommandTest extends RepositoryTestCase {
@@ -740,11 +739,9 @@ public void testSmudgeFilter_deleteFileAndCreateBranchAndRestoreFromCommit()
 	}
 
 	@Test
-	@Ignore
-	public void testSmudgeAndClean() throws IOException, GitAPIException {
-		// @TODO: fix this test
-		File clean_filter = writeTempFile("sed s/V1/@version/g -");
-		File smudge_filter = writeTempFile("sed s/@version/V1/g -");
+	public void testSmudgeAndClean() throws Exception {
+		File clean_filter = writeTempFile("sed s/V1/@version/g");
+		File smudge_filter = writeTempFile("sed s/@version/V1/g");
 
 		try (Git git2 = new Git(db)) {
 			StoredConfig config = git.getRepository().getConfig();
@@ -753,33 +750,39 @@ public void testSmudgeAndClean() throws IOException, GitAPIException {
 			config.setString("filter", "tstFilter", "clean",
 					"sh " + slashify(clean_filter.getPath()));
 			config.save();
-			writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
+			writeTrashFile(".gitattributes", "filterTest.txt filter=tstFilter");
 			git2.add().addFilepattern(".gitattributes").call();
 			git2.commit().setMessage("add attributes").call();
 
-			writeTrashFile("filterTest.txt", "hello world, V1");
+			fsTick(writeTrashFile("filterTest.txt", "hello world, V1\n"));
 			git2.add().addFilepattern("filterTest.txt").call();
-			git2.commit().setMessage("add filterText.txt").call();
+			RevCommit one = git2.commit().setMessage("add filterText.txt").call();
 			assertEquals(
-					"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some other change][filterTest.txt, mode:100644, content:hello world, @version]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:hello world, @version\n]",
 					indexState(CONTENT));
 
-			git2.checkout().setCreateBranch(true).setName("test2").call();
-			writeTrashFile("filterTest.txt", "bon giorno world, V1");
+			fsTick(writeTrashFile("filterTest.txt", "bon giorno world, V1\n"));
 			git2.add().addFilepattern("filterTest.txt").call();
-			git2.commit().setMessage("modified filterText.txt").call();
+			RevCommit two = git2.commit().setMessage("modified filterTest.txt").call();
 
 			assertTrue(git2.status().call().isClean());
 			assertEquals(
-					"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some other change][filterTest.txt, mode:100644, content:bon giorno world, @version]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:bon giorno world, @version\n]",
 					indexState(CONTENT));
 
-			git2.checkout().setName("refs/heads/test").call();
+			git2.checkout().setName(one.getName()).call();
 			assertTrue(git2.status().call().isClean());
 			assertEquals(
-					"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some other change][filterTest.txt, mode:100644, content:hello world, @version]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:hello world, @version\n]",
 					indexState(CONTENT));
-			assertEquals("hello world, V1", read("filterTest.txt"));
+			assertEquals("hello world, V1\n", read("filterTest.txt"));
+
+			git2.checkout().setName(two.getName()).call();
+			assertTrue(git2.status().call().isClean());
+			assertEquals(
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:bon giorno world, @version\n]",
+					indexState(CONTENT));
+			assertEquals("bon giorno world, V1\n", read("filterTest.txt"));
 		}
 	}
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java
index 5dd8da5..5f10131 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java
@@ -51,6 +51,7 @@
 import org.eclipse.jgit.api.errors.NoFilepatternException;
 import org.eclipse.jgit.attributes.Attribute;
 import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEditor;
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.dircache.DirCacheIterator;
 import org.eclipse.jgit.errors.RevisionSyntaxException;
@@ -61,9 +62,11 @@
 import org.eclipse.jgit.lib.CoreConfig.EOL;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.treewalk.FileTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.IO;
 import org.junit.Assert;
 import org.junit.Test;
@@ -83,6 +86,14 @@ public class EolRepositoryTest extends RepositoryTestCase {
 	private static final FileMode F = FileMode.REGULAR_FILE;
 
 	@DataPoint
+	public static boolean doSmudgeEntries = true;
+
+	@DataPoint
+	public static boolean dontSmudgeEntries = false;
+
+	private boolean smudge;
+
+	@DataPoint
 	public static String smallContents[] = {
 			generateTestData(3, 1, true, false),
 			generateTestData(3, 1, false, true),
@@ -117,10 +128,11 @@ static String generateTestData(int size, int lineSize, boolean withCRLF,
 		return sb.toString();
 	}
 
-	public EolRepositoryTest(String[] testContent) {
+	public EolRepositoryTest(String[] testContent, boolean smudgeEntries) {
 		CONTENT_CRLF = testContent[0];
 		CONTENT_LF = testContent[1];
 		CONTENT_MIXED = testContent[2];
+		this.smudge = smudgeEntries;
 	}
 
 	protected String CONTENT_CRLF;
@@ -160,7 +172,7 @@ private static class ActualEntry {
 
 	private ActualEntry entryMixed = new ActualEntry();
 
-	private DirCache dc;
+	private DirCache dirCache;
 
 	@Test
 	public void testDefaultSetup() throws Exception {
@@ -177,7 +189,9 @@ public void checkEntryContent(ActualEntry entry, String fileContent,
 			String indexContent) {
 		assertEquals(fileContent, entry.file);
 		assertEquals(indexContent, entry.index);
-		assertEquals(fileContent.length(), entry.indexContentLength);
+		if (entry.indexContentLength != 0) {
+			assertEquals(fileContent.length(), entry.indexContentLength);
+		}
 	}
 
 	@Test
@@ -584,6 +598,14 @@ private void setupGitAndDoHardReset(AutoCRLF autoCRLF, EOL eol,
 			dotGitattributes = null;
 		}
 
+		fileCRLF = createAndAddFile(git, "file1.txt", "a");
+
+		fileLF = createAndAddFile(git, "file2.txt", "a");
+
+		fileMixed = createAndAddFile(git, "file3.txt", "a");
+
+		RevCommit c = gitCommit(git, "create files");
+
 		fileCRLF = createAndAddFile(git, "file1.txt", CONTENT_CRLF);
 
 		fileLF = createAndAddFile(git, "file2.txt", CONTENT_LF);
@@ -593,6 +615,26 @@ private void setupGitAndDoHardReset(AutoCRLF autoCRLF, EOL eol,
 		gitCommit(git, "addFiles");
 
 		recreateWorktree(git);
+
+		if (smudge) {
+			DirCache dc = DirCache.lock(git.getRepository().getIndexFile(),
+					FS.detect());
+			DirCacheEditor editor = dc.editor();
+			for (int i = 0; i < dc.getEntryCount(); i++) {
+				editor.add(new DirCacheEditor.PathEdit(
+						dc.getEntry(i).getPathString()) {
+					public void apply(DirCacheEntry ent) {
+						ent.smudgeRacilyClean();
+					}
+				});
+			}
+			editor.commit();
+		}
+
+		// @TODO: find out why the following assertion would break the tests
+		// assertTrue(git.status().call().isClean());
+		git.checkout().setName(c.getName()).call();
+		git.checkout().setName("master").call();
 	}
 
 	private void recreateWorktree(Git git)
@@ -610,8 +652,8 @@ private void recreateWorktree(Git git)
 		gitAdd(git, ".");
 	}
 
-	protected void gitCommit(Git git, String msg) throws GitAPIException {
-		git.commit().setMessage(msg).call();
+	protected RevCommit gitCommit(Git git, String msg) throws GitAPIException {
+		return git.commit().setMessage(msg).call();
 	}
 
 	protected void gitAdd(Git git, String path) throws GitAPIException {
@@ -644,7 +686,7 @@ private File createAndAddFile(Git git, String path, String content)
 	}
 
 	private void collectRepositoryState() throws Exception {
-		dc = db.readDirCache();
+		dirCache = db.readDirCache();
 		walk = beginWalk();
 		if (dotGitattributes != null)
 			collectEntryContentAndAttributes(F, ".gitattributes", null);
@@ -680,7 +722,7 @@ private void collectEntryContentAndAttributes(FileMode type, String pathName,
 			e.attrs = e.attrs.trim();
 			e.file = new String(
 					IO.readFully(new File(db.getWorkTree(), pathName)));
-			DirCacheEntry dce = dc.getEntry(pathName);
+			DirCacheEntry dce = dirCache.getEntry(pathName);
 			ObjectLoader open = walk.getObjectReader().open(dce.getObjectId());
 			e.index = new String(open.getBytes());
 			e.indexContentLength = dce.getLength();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
index bde450f..8fbf839 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
@@ -223,12 +223,16 @@ private void apply(File f, FileHeader fh)
 					pos++;
 					break;
 				case '-':
-					if (!newLines.get(hh.getNewStartLine() - 1 + pos).equals(
-							hunkLine.substring(1))) {
-						throw new PatchApplyException(MessageFormat.format(
-								JGitText.get().patchApplyException, hh));
+					if (hh.getNewStartLine() == 0) {
+						newLines.clear();
+					} else {
+						if (!newLines.get(hh.getNewStartLine() - 1 + pos)
+								.equals(hunkLine.substring(1))) {
+							throw new PatchApplyException(MessageFormat.format(
+									JGitText.get().patchApplyException, hh));
+						}
+						newLines.remove(hh.getNewStartLine() - 1 + pos);
 					}
-					newLines.remove(hh.getNewStartLine() - 1 + pos);
 					break;
 				case '+':
 					newLines.add(hh.getNewStartLine() - 1 + pos,
@@ -250,7 +254,9 @@ private void apply(File f, FileHeader fh)
 			// still there!
 			sb.append(l).append('\n');
 		}
-		sb.deleteCharAt(sb.length() - 1);
+		if (sb.length() > 0) {
+			sb.deleteCharAt(sb.length() - 1);
+		}
 		FileWriter fw = new FileWriter(f);
 		fw.write(sb.toString());
 		fw.close();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 3fcaa38..fc4cc90 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -280,8 +280,9 @@ public void preScanTwoTrees() throws CorruptObjectException, IOException {
 
 		addTree(walk, headCommitTree);
 		addTree(walk, mergeCommitTree);
-		walk.addTree(new DirCacheBuildIterator(builder));
+		int dciPos = walk.addTree(new DirCacheBuildIterator(builder));
 		walk.addTree(workingTree);
+		workingTree.setDirCacheIterator(walk, dciPos);
 
 		while (walk.next()) {
 			processEntry(walk.getTree(0, CanonicalTreeParser.class),
@@ -320,8 +321,9 @@ public void prescanOneTree()
 
 		walk = new NameConflictTreeWalk(repo);
 		addTree(walk, mergeCommitTree);
-		walk.addTree(new DirCacheBuildIterator(builder));
+		int dciPos = walk.addTree(new DirCacheBuildIterator(builder));
 		walk.addTree(workingTree);
+		workingTree.setDirCacheIterator(walk, dciPos);
 
 		while (walk.next()) {
 			processEntry(walk.getTree(0, CanonicalTreeParser.class),
@@ -1093,8 +1095,10 @@ private void cleanUpConflicts() throws CheckoutConflictException {
 	private boolean isModifiedSubtree_IndexWorkingtree(String path)
 			throws CorruptObjectException, IOException {
 		try (NameConflictTreeWalk tw = new NameConflictTreeWalk(repo)) {
-			tw.addTree(new DirCacheIterator(dc));
-			tw.addTree(new FileTreeIterator(repo));
+			int dciPos = tw.addTree(new DirCacheIterator(dc));
+			FileTreeIterator fti = new FileTreeIterator(repo);
+			tw.addTree(fti);
+			fti.setDirCacheIterator(tw, dciPos);
 			tw.setRecursive(true);
 			tw.setFilter(PathFilter.create(path));
 			DirCacheIterator dcIt;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index 6f3166a..4bb2982 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -312,11 +312,10 @@ public Ref getRef(final String needle) throws IOException {
 
 	@Override
 	public Map<String, Ref> getRefs(String prefix) throws IOException {
-		final RefList<Ref> packed = getPackedRefs();
 		final RefList<LooseRef> oldLoose = looseRefs.get();
-
 		LooseScanner scan = new LooseScanner(oldLoose);
 		scan.scan(prefix);
+		final RefList<Ref> packed = getPackedRefs();
 
 		RefList<LooseRef> loose;
 		if (scan.newLoose != null) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index de08e4b..e224d71 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -1005,13 +1005,14 @@ protected boolean mergeTrees(AbstractTreeIterator baseTree,
 		builder = dircache.builder();
 		DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder);
 
-		tw = new NameConflictTreeWalk(reader);
+		tw = new NameConflictTreeWalk(db, reader);
 		tw.addTree(baseTree);
 		tw.addTree(headTree);
 		tw.addTree(mergeTree);
-		tw.addTree(buildIt);
+		int dciPos = tw.addTree(buildIt);
 		if (workingTreeIterator != null) {
 			tw.addTree(workingTreeIterator);
+			workingTreeIterator.setDirCacheIterator(tw, dciPos);
 		} else {
 			tw.setFilter(TreeFilter.ANY_DIFF);
 		}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
index f18a522..ec903c1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
@@ -106,7 +106,7 @@ private static class InCoreMerger extends ThreeWayMerger {
 
 		InCoreMerger(final Repository local) {
 			super(local);
-			tw = new NameConflictTreeWalk(reader);
+			tw = new NameConflictTreeWalk(local, reader);
 			cache = DirCache.newInCore();
 		}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
index 501d676..7dac50a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
@@ -580,16 +580,30 @@ public Attributes getAttributes() {
 	}
 
 	/**
+	 * @param opType
+	 *            the operationtype (checkin/checkout) which should be used
+	 * @return the EOL stream type of the current entry using the config and
+	 *         {@link #getAttributes()} Note that this method may return null if
+	 *         the {@link TreeWalk} is not based on a working tree
+	 */
+	// TODO(msohn) make this method public in 4.4
+	@Nullable
+	EolStreamType getEolStreamType(OperationType opType) {
+			if (attributesNodeProvider == null || config == null)
+				return null;
+		return EolStreamTypeUtil.detectStreamType(opType,
+					config.get(WorkingTreeOptions.KEY), getAttributes());
+	}
+
+	/**
 	 * @return the EOL stream type of the current entry using the config and
 	 *         {@link #getAttributes()} Note that this method may return null if
 	 *         the {@link TreeWalk} is not based on a working tree
 	 * @since 4.3
 	 */
+	// TODO(msohn) deprecate this method in 4.4
 	public @Nullable EolStreamType getEolStreamType() {
-			if (attributesNodeProvider == null || config == null)
-				return null;
-			return EolStreamTypeUtil.detectStreamType(operationType,
-					config.get(WorkingTreeOptions.KEY), getAttributes());
+		return (getEolStreamType(operationType));
 	}
 
 	/** Reset this walker so new tree iterators can be added to it. */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index 39176c6..c8de3de 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -86,6 +86,7 @@
 import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.submodule.SubmoduleWalk;
+import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.FS.ExecutionResult;
 import org.eclipse.jgit.util.Holder;
@@ -361,7 +362,8 @@ public boolean isWorkTree() {
 				state.initializeDigestAndReadBuffer();
 
 				final long len = e.getLength();
-				InputStream filteredIs = possiblyFilteredInputStream(e, is, len);
+				InputStream filteredIs = possiblyFilteredInputStream(e, is, len,
+						OperationType.CHECKIN_OP);
 				return computeHash(filteredIs, canonLen);
 			} finally {
 				safeClose(is);
@@ -374,8 +376,15 @@ public boolean isWorkTree() {
 
 	private InputStream possiblyFilteredInputStream(final Entry e,
 			final InputStream is, final long len) throws IOException {
+		return possiblyFilteredInputStream(e, is, len, null);
+
+	}
+
+	private InputStream possiblyFilteredInputStream(final Entry e,
+			final InputStream is, final long len, OperationType opType)
+			throws IOException {
 		if (getCleanFilterCommand() == null
-				&& getEolStreamType() == EolStreamType.DIRECT) {
+				&& getEolStreamType(opType) == EolStreamType.DIRECT) {
 			canonLen = len;
 			return is;
 		}
@@ -385,7 +394,7 @@ && getEolStreamType() == EolStreamType.DIRECT) {
 			byte[] raw = rawbuf.array();
 			int n = rawbuf.limit();
 			if (!isBinary(raw, n)) {
-				rawbuf = filterClean(raw, n);
+				rawbuf = filterClean(raw, n, opType);
 				raw = rawbuf.array();
 				n = rawbuf.limit();
 			}
@@ -398,13 +407,14 @@ && getEolStreamType() == EolStreamType.DIRECT) {
 				return is;
 			}
 
-		final InputStream lenIs = filterClean(e.openInputStream());
+		final InputStream lenIs = filterClean(e.openInputStream(),
+				opType);
 		try {
 			canonLen = computeLength(lenIs);
 		} finally {
 			safeClose(lenIs);
 		}
-		return filterClean(is);
+		return filterClean(is, opType);
 	}
 
 	private static void safeClose(final InputStream in) {
@@ -430,17 +440,23 @@ private static boolean isBinary(Entry entry) throws IOException {
 		}
 	}
 
-	private ByteBuffer filterClean(byte[] src, int n) throws IOException {
+	private ByteBuffer filterClean(byte[] src, int n, OperationType opType)
+			throws IOException {
 		InputStream in = new ByteArrayInputStream(src);
 		try {
-			return IO.readWholeStream(filterClean(in), n);
+			return IO.readWholeStream(filterClean(in, opType), n);
 		} finally {
 			safeClose(in);
 		}
 	}
 
 	private InputStream filterClean(InputStream in) throws IOException {
-		in = handleAutoCRLF(in);
+		return filterClean(in, null);
+	}
+
+	private InputStream filterClean(InputStream in, OperationType opType)
+			throws IOException {
+		in = handleAutoCRLF(in, opType);
 		String filterCommand = getCleanFilterCommand();
 		if (filterCommand != null) {
 			FS fs = repository.getFS();
@@ -469,8 +485,9 @@ filterCommand, getEntryPathString(),
 		return in;
 	}
 
-	private InputStream handleAutoCRLF(InputStream in) throws IOException {
-		return EolStreamTypeUtil.wrapInputStream(in, getEolStreamType());
+	private InputStream handleAutoCRLF(InputStream in, OperationType opType)
+			throws IOException {
+		return EolStreamTypeUtil.wrapInputStream(in, getEolStreamType(opType));
 	}
 
 	/**
@@ -1332,10 +1349,28 @@ public String getCleanFilterCommand() throws IOException {
 	 * @since 4.3
 	 */
 	public EolStreamType getEolStreamType() throws IOException {
+		return getEolStreamType(null);
+	}
+
+	/**
+	 * @param opType
+	 *            The operationtype (checkin/checkout) which should be used
+	 * @return the eol stream type for the current entry or <code>null</code> if
+	 *         it cannot be determined. When state or state.walk is null or the
+	 *         {@link TreeWalk} is not based on a {@link Repository} then null
+	 *         is returned.
+	 * @throws IOException
+	 */
+	private EolStreamType getEolStreamType(OperationType opType)
+			throws IOException {
 		if (eolStreamTypeHolder == null) {
 			EolStreamType type=null;
 			if (state.walk != null) {
-				type=state.walk.getEolStreamType();
+				if (opType != null) {
+					type = state.walk.getEolStreamType(opType);
+				} else {
+					type=state.walk.getEolStreamType();
+				}
 			} else {
 				switch (getOptions().getAutoCRLF()) {
 				case FALSE:
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
index 6a43c0f..7cb2bf6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
@@ -189,7 +189,8 @@ public static int response(final HttpConnection c) throws IOException {
 		try {
 			return c.getResponseCode();
 		} catch (ConnectException ce) {
-			final String host = c.getURL().getHost();
+			final URL url = c.getURL();
+			final String host = (url == null) ? "<null>" : url.getHost();
 			// The standard J2SE error message is not very useful.
 			//
 			if ("Connection timed out: connect".equals(ce.getMessage())) //$NON-NLS-1$
@@ -216,7 +217,8 @@ public static int response(final java.net.HttpURLConnection c)
 		try {
 			return c.getResponseCode();
 		} catch (ConnectException ce) {
-			final String host = c.getURL().getHost();
+			final URL url = c.getURL();
+			final String host = (url == null) ? "<null>" : url.getHost();
 			// The standard J2SE error message is not very useful.
 			//
 			if ("Connection timed out: connect".equals(ce.getMessage())) //$NON-NLS-1$