diff options
author | Preben Ingvaldsen <preben@puppetlabs.com> | 2016-03-01 11:37:54 -0800 |
---|---|---|
committer | Christian Halstrick <christian.halstrick@sap.com> | 2016-04-05 10:43:40 +0200 |
commit | 403f04d8dd744a6cc1c2a61540c34483b94c06b5 (patch) | |
tree | 09caf267b9c0808b9c93c1217b5dfebadde322be /org.eclipse.jgit | |
parent | bf32c9102fb1b5fdfa7a26a120b5d9a6b428dd2f (diff) | |
download | jgit-403f04d8dd744a6cc1c2a61540c34483b94c06b5.tar.gz jgit-403f04d8dd744a6cc1c2a61540c34483b94c06b5.zip |
Implement DIR_NO_GITLINKS
Implement the DIR_NO_GITLINKS setting with the same functionality
it provides in cGit.
Bug: 436200
Change-Id: I8304e42df2d7e8d7925f515805e075a92ff6ce28
Signed-off-by: Preben Ingvaldsen <preben@puppetlabs.com>
Diffstat (limited to 'org.eclipse.jgit')
7 files changed, 99 insertions, 11 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java index 3b94f16f1a..1f37833a41 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.api; import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; import static org.eclipse.jgit.lib.FileMode.GITLINK; +import static org.eclipse.jgit.lib.FileMode.TYPE_GITLINK; import static org.eclipse.jgit.lib.FileMode.TYPE_TREE; import java.io.IOException; @@ -201,7 +202,10 @@ public class AddCommand extends GitCommand<DirCache> { continue; } - if (f.getEntryRawMode() == TYPE_TREE) { + if ((f.getEntryRawMode() == TYPE_TREE + && f.getIndexFileMode(c) != FileMode.GITLINK) || + (f.getEntryRawMode() == TYPE_GITLINK + && f.getIndexFileMode(c) == FileMode.TREE)) { // Index entry exists and is symlink, gitlink or file, // otherwise the tree would have been entered above. // Replace the index entry by diving into tree of files. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java index 054d193017..abc8c269ff 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java @@ -235,6 +235,12 @@ public class ConfigConstants { */ public static final String CONFIG_KEY_HIDEDOTFILES = "hidedotfiles"; + /** + * The "dirnogitlinks" key + * @since 4.3 + */ + public static final String CONFIG_KEY_DIRNOGITLINKS = "dirNoGitLinks"; + /** The "precomposeunicode" key */ public static final String CONFIG_KEY_PRECOMPOSEUNICODE = "precomposeunicode"; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java index dc835e4f36..07fc829db4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java @@ -729,4 +729,13 @@ public abstract class AbstractTreeIterator { public String toString() { return getClass().getSimpleName() + "[" + getEntryPathString() + "]"; //$NON-NLS-1$ } + + /** + * @return whether or not this Iterator is iterating through the Work Tree + * + * @since 4.3 + */ + public boolean isWorkTree() { + return false; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java index eb4f1a87d0..db81e1af9b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java @@ -94,7 +94,10 @@ public class FileTreeIterator extends WorkingTreeIterator { * the repository whose working tree will be scanned. */ public FileTreeIterator(Repository repo) { - this(repo, DefaultFileModeStrategy.INSTANCE); + this(repo, + repo.getConfig().get(WorkingTreeOptions.KEY).isDirNoGitLinks() ? + NoGitlinksStrategy.INSTANCE : + DefaultFileModeStrategy.INSTANCE); } /** @@ -291,6 +294,35 @@ public class FileTreeIterator extends WorkingTreeIterator { } } + /** + * A FileModeStrategy that implements native git's DIR_NO_GITLINKS + * behavior. This is the same as the default FileModeStrategy, except + * all directories will be treated as directories regardless of whether + * or not they contain a .git directory or file. + * + * @since 4.3 + */ + static public class NoGitlinksStrategy implements FileModeStrategy { + + /** + * a singleton instance of the default FileModeStrategy + */ + public final static NoGitlinksStrategy INSTANCE = new NoGitlinksStrategy(); + + @Override + public FileMode getMode(File f, FS.Attributes attributes) { + if (attributes.isSymbolicLink()) { + return FileMode.SYMLINK; + } else if (attributes.isDirectory()) { + return FileMode.TREE; + } else if (attributes.isExecutable()) { + return FileMode.EXECUTABLE_FILE; + } else { + return FileMode.REGULAR_FILE; + } + } + } + /** * Wrapper for a standard Java IO file 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 aecbac11ea..501d676735 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java @@ -1187,7 +1187,12 @@ public class TreeWalk implements AutoCloseable, AttributesProvider { for (int i = 0; i < trees.length; i++) { final AbstractTreeIterator t = trees[i]; final AbstractTreeIterator n; - if (t.matches == ch && !t.eof() && FileMode.TREE.equals(t.mode)) + // If we find a GITLINK when attempting to enter a subtree, then the + // GITLINK must exist as a TREE in the index, meaning the working tree + // entry should be treated as a TREE + if (t.matches == ch && !t.eof() && + (FileMode.TREE.equals(t.mode) + || (FileMode.GITLINK.equals(t.mode) && t.isWorkTree()))) n = t.createSubtreeIterator(reader, idBuffer); else n = t.createEmptyTreeIterator(); 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 ca8f9aa373..39176c621e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -264,7 +264,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { // the cached index information for the path. // DirCacheIterator i = state.walk.getTree(state.dirCacheTree, - DirCacheIterator.class); + DirCacheIterator.class); if (i != null) { DirCacheEntry ent = i.getDirCacheEntry(); if (ent != null && compareMetadata(ent) == MetadataDiff.EQUAL) { @@ -289,6 +289,11 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { return zeroid; } + @Override + public boolean isWorkTree() { + return true; + } + /** * Get submodule id for given entry. * @@ -916,17 +921,31 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { */ public FileMode getIndexFileMode(final DirCacheIterator indexIter) { final FileMode wtMode = getEntryFileMode(); - if (indexIter == null) - return wtMode; - if (getOptions().isFileMode()) + if (indexIter == null) { return wtMode; + } final FileMode iMode = indexIter.getEntryFileMode(); - if (FileMode.REGULAR_FILE == wtMode - && FileMode.EXECUTABLE_FILE == iMode) + if (getOptions().isFileMode() && iMode != FileMode.GITLINK && iMode != FileMode.TREE) { + return wtMode; + } + if (!getOptions().isFileMode()) { + if (FileMode.REGULAR_FILE == wtMode + && FileMode.EXECUTABLE_FILE == iMode) { + return iMode; + } + if (FileMode.EXECUTABLE_FILE == wtMode + && FileMode.REGULAR_FILE == iMode) { + return iMode; + } + } + if (FileMode.GITLINK == iMode + && FileMode.TREE == wtMode) { return iMode; - if (FileMode.EXECUTABLE_FILE == wtMode - && FileMode.REGULAR_FILE == iMode) + } + if (FileMode.TREE == iMode + && FileMode.GITLINK == wtMode) { return iMode; + } return wtMode; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java index a8990b1e95..dea07c1973 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java @@ -73,6 +73,8 @@ public class WorkingTreeOptions { private final HideDotFiles hideDotFiles; + private final boolean dirNoGitLinks; + private WorkingTreeOptions(final Config rc) { fileMode = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION, ConfigConstants.CONFIG_KEY_FILEMODE, true); @@ -87,6 +89,9 @@ public class WorkingTreeOptions { hideDotFiles = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_HIDEDOTFILES, HideDotFiles.DOTGITONLY); + dirNoGitLinks = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_DIRNOGITLINKS, + false); } /** @return true if the execute bit on working files should be trusted. */ @@ -131,4 +136,12 @@ public class WorkingTreeOptions { public HideDotFiles getHideDotFiles() { return hideDotFiles; } + + /** + * @return whether or not we treat nested repos as directories. + * If true, folders containing .git entries will not be + * treated as gitlinks. + * @since 4.3 + */ + public boolean isDirNoGitLinks() { return dirNoGitLinks; } } |