/*
- * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
+ * Copyright (C) 2011, 2013 Dariusz Luksza <dariusz@luksza.org>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.FileUtils;
import org.junit.Test;
assertThat(entry.getNewPath(), is("b.txt"));
}
+ @Test
+ public void shouldMarkEntriesWhenGivenMarkTreeFilter() throws Exception {
+ // given
+ Git git = new Git(db);
+ RevCommit c1 = git.commit().setMessage("initial commit").call();
+ FileUtils.mkdir(new File(db.getWorkTree(), "b"));
+ writeTrashFile("a.txt", "a");
+ writeTrashFile("b/1.txt", "b1");
+ writeTrashFile("b/2.txt", "b2");
+ writeTrashFile("c.txt", "c");
+ git.add().addFilepattern("a.txt").addFilepattern("b")
+ .addFilepattern("c.txt").call();
+ RevCommit c2 = git.commit().setMessage("second commit").call();
+ TreeFilter filterA = PathFilterGroup.createFromStrings("a.txt");
+ TreeFilter filterB = PathFilterGroup.createFromStrings("b");
+ TreeFilter filterB2 = PathFilterGroup.createFromStrings("b/2.txt");
+
+ // when
+ TreeWalk walk = new TreeWalk(db);
+ walk.addTree(c1.getTree());
+ walk.addTree(c2.getTree());
+ List<DiffEntry> result = DiffEntry.scan(walk, true, new TreeFilter[] {
+ filterA, filterB, filterB2 });
+
+ // then
+ assertThat(result, notNullValue());
+ assertEquals(5, result.size());
+
+ DiffEntry entryA = result.get(0);
+ DiffEntry entryB = result.get(1);
+ DiffEntry entryB1 = result.get(2);
+ DiffEntry entryB2 = result.get(3);
+ DiffEntry entryC = result.get(4);
+
+ assertThat(entryA.getNewPath(), is("a.txt"));
+ assertTrue(entryA.isMarked(0));
+ assertFalse(entryA.isMarked(1));
+ assertFalse(entryA.isMarked(2));
+ assertEquals(1, entryA.getTreeFilterMarks());
+
+ assertThat(entryB.getNewPath(), is("b"));
+ assertFalse(entryB.isMarked(0));
+ assertTrue(entryB.isMarked(1));
+ assertTrue(entryB.isMarked(2));
+ assertEquals(6, entryB.getTreeFilterMarks());
+
+ assertThat(entryB1.getNewPath(), is("b/1.txt"));
+ assertFalse(entryB1.isMarked(0));
+ assertTrue(entryB1.isMarked(1));
+ assertFalse(entryB1.isMarked(2));
+ assertEquals(2, entryB1.getTreeFilterMarks());
+
+ assertThat(entryB2.getNewPath(), is("b/2.txt"));
+ assertFalse(entryB2.isMarked(0));
+ assertTrue(entryB2.isMarked(1));
+ assertTrue(entryB2.isMarked(2));
+ assertEquals(6, entryB2.getTreeFilterMarks());
+
+ assertThat(entryC.getNewPath(), is("c.txt"));
+ assertFalse(entryC.isMarked(0));
+ assertFalse(entryC.isMarked(1));
+ assertFalse(entryC.isMarked(2));
+ assertEquals(0, entryC.getTreeFilterMarks());
+ }
+
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIAEWhenTreeWalkHasLessThanTwoTrees()
throws Exception {
transportProtoSFTP=SFTP
transportProtoSSH=SSH
treeEntryAlreadyExists=Tree entry "{0}" already exists.
+treeFilterMarkerTooManyFilters=Too many markTreeFilters passed, maximum number is {0} (passed {1})
treeIteratorDoesNotSupportRemove=TreeIterator does not support remove()
treeWalkMustHaveExactlyTwoTrees=TreeWalk should have exactly two trees.
truncatedHunkLinesMissingForAncestor=Truncated hunk, at least {0} lines missing for ancestor {1}
/*
- * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008-2013, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilterMarker;
/** A value class representing a change to a file */
public class DiffEntry {
* when {@code includeTrees} parameter is {@code true} it can't
* be recursive.
* @param includeTrees
- * include tree object's.
+ * include tree objects.
* @return headers describing the changed files.
* @throws IOException
* the repository cannot be accessed.
*/
public static List<DiffEntry> scan(TreeWalk walk, boolean includeTrees)
throws IOException {
+ return scan(walk, includeTrees, null);
+ }
+
+ /**
+ * Convert the TreeWalk into DiffEntry headers, depending on
+ * {@code includeTrees} it will add tree objects into result or not.
+ *
+ * @param walk
+ * the TreeWalk to walk through. Must have exactly two trees and
+ * when {@code includeTrees} parameter is {@code true} it can't
+ * be recursive.
+ * @param includeTrees
+ * include tree objects.
+ * @param markTreeFilters
+ * array of tree filters which will be tested for each entry. If
+ * an entry matches, the entry will later return true when
+ * queried through {{@link #isMarked(int)} (with the index from
+ * this passed array).
+ * @return headers describing the changed files.
+ * @throws IOException
+ * the repository cannot be accessed.
+ * @throws IllegalArgumentException
+ * when {@code includeTrees} is true and given TreeWalk is
+ * recursive. Or when given TreeWalk doesn't have exactly two
+ * trees
+ * @since 2.3
+ */
+ public static List<DiffEntry> scan(TreeWalk walk, boolean includeTrees,
+ TreeFilter[] markTreeFilters)
+ throws IOException {
if (walk.getTreeCount() != 2)
throw new IllegalArgumentException(
JGitText.get().treeWalkMustHaveExactlyTwoTrees);
throw new IllegalArgumentException(
JGitText.get().cannotBeRecursiveWhenTreesAreIncluded);
+ TreeFilterMarker treeFilterMarker;
+ if (markTreeFilters != null && markTreeFilters.length > 0)
+ treeFilterMarker = new TreeFilterMarker(markTreeFilters);
+ else
+ treeFilterMarker = null;
+
List<DiffEntry> r = new ArrayList<DiffEntry>();
MutableObjectId idBuf = new MutableObjectId();
while (walk.next()) {
entry.newMode = walk.getFileMode(1);
entry.newPath = entry.oldPath = walk.getPathString();
+ if (treeFilterMarker != null)
+ entry.treeFilterMarks = treeFilterMarker.getMarks(walk);
+
if (entry.oldMode == FileMode.MISSING) {
entry.oldPath = DiffEntry.DEV_NULL;
entry.changeType = ChangeType.ADD;
/** ObjectId listed on the index line for the new (post-image) */
protected AbbreviatedObjectId newId;
+ /**
+ * Bitset for marked flags of tree filters passed to
+ * {@link #scan(TreeWalk, boolean, TreeFilter...)}
+ */
+ private int treeFilterMarks = 0;
+
/**
* Get the old name associated with this file.
* <p>
return newId;
}
+ /**
+ * Whether the mark tree filter with the specified index matched during scan
+ * or not, see {@link #scan(TreeWalk, boolean, TreeFilter...)}. Example:
+ * <p>
+ *
+ * <pre>
+ * TreeFilter filterA = ...;
+ * TreeFilter filterB = ...;
+ * List<DiffEntry> entries = DiffEntry.scan(walk, false, filterA, filterB);
+ * DiffEntry entry = entries.get(0);
+ * boolean filterAMatched = entry.isMarked(0);
+ * boolean filterBMatched = entry.isMarked(1);
+ * </pre>
+ * <p>
+ * Note that 0 corresponds to filterA because it was the first filter that
+ * was passed to scan.
+ * <p>
+ * To query more than one flag at once, see {@link #getTreeFilterMarks()}.
+ *
+ * @param index
+ * the index of the tree filter to check for (must be between 0
+ * and {@link Integer#SIZE}).
+ *
+ * @return true, if the tree filter matched; false if not
+ * @since 2.3
+ */
+ public boolean isMarked(int index) {
+ return (treeFilterMarks & (1L << index)) != 0;
+ }
+
+ /**
+ * Get the raw tree filter marks, as set during
+ * {@link #scan(TreeWalk, boolean, TreeFilter...)}. See
+ * {@link #isMarked(int)} to query each mark individually.
+ *
+ * @return the bitset of tree filter marks
+ * @since 2.3
+ */
+ public int getTreeFilterMarks() {
+ return treeFilterMarks;
+ }
+
/**
* Get the object id.
*
/*
- * Copyright (C) 2010, Sasa Zivkov <sasa.zivkov@sap.com>
+ * Copyright (C) 2010, 2013 Sasa Zivkov <sasa.zivkov@sap.com>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
/***/ public String transportProtoSFTP;
/***/ public String transportProtoSSH;
/***/ public String treeEntryAlreadyExists;
+ /***/ public String treeFilterMarkerTooManyFilters;
/***/ public String treeIteratorDoesNotSupportRemove;
/***/ public String treeWalkMustHaveExactlyTwoTrees;
/***/ public String truncatedHunkLinesMissingForAncestor;
--- /dev/null
+/*
+ * Copyright (C) 2013, Robin Stocker <robin@nibor.org>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * 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 Eclipse Foundation, Inc. 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.eclipse.jgit.treewalk.filter;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StopWalkException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.treewalk.TreeWalk;
+
+/**
+ * For testing an array of {@link TreeFilter} during a {@link TreeWalk} for each
+ * entry and returning the result as a bitmask.
+ *
+ * @since 2.3
+ */
+public class TreeFilterMarker {
+
+ private final TreeFilter[] filters;
+
+ /**
+ * Construct a TreeFilterMarker. Note that it is stateful and can only be
+ * used for one walk loop.
+ *
+ * @param markTreeFilters
+ * the filters to use for marking, must not have more elements
+ * than {@link Integer#SIZE}.
+ * @throws IllegalArgumentException
+ * if more tree filters are passed than possible
+ */
+ public TreeFilterMarker(TreeFilter[] markTreeFilters) {
+ if (markTreeFilters.length > Integer.SIZE) {
+ throw new IllegalArgumentException(MessageFormat.format(
+ JGitText.get().treeFilterMarkerTooManyFilters,
+ Integer.valueOf(Integer.SIZE),
+ Integer.valueOf(markTreeFilters.length)));
+ }
+ filters = new TreeFilter[markTreeFilters.length];
+ System.arraycopy(markTreeFilters, 0, filters, 0, markTreeFilters.length);
+ }
+
+ /**
+ * Test the filters against the walk. Returns a bitmask where each bit
+ * represents the result of a call to {@link TreeFilter#include(TreeWalk)},
+ * ordered by the index for which the tree filters were passed in the
+ * constructor.
+ *
+ * @param walk
+ * the walk from which to test the current entry
+ * @return the marks bitmask
+ * @throws MissingObjectException
+ * as thrown by {@link TreeFilter#include(TreeWalk)}
+ * @throws IncorrectObjectTypeException
+ * as thrown by {@link TreeFilter#include(TreeWalk)}
+ * @throws IOException
+ * as thrown by {@link TreeFilter#include(TreeWalk)}
+ */
+ public int getMarks(TreeWalk walk) throws MissingObjectException,
+ IncorrectObjectTypeException, IOException {
+ int marks = 0;
+ for (int index = 0; index < filters.length; index++) {
+ TreeFilter filter = filters[index];
+ if (filter != null) {
+ try {
+ boolean marked = filter.include(walk);
+ if (marked)
+ marks |= (1L << index);
+ } catch (StopWalkException e) {
+ // Don't check tree filter anymore, it will no longer
+ // match
+ filters[index] = null;
+ }
+ }
+ }
+ return marks;
+ }
+
+}