Browse Source
Respect merge=lfs and diff=lfs attributes where required to replace (in memory) the content of LFS pointers with the actual blob content from the LFS storage (and vice versa when staging/merging). Does not implement general support for merge/diff attributes for any other use case apart from LFS. Change-Id: Ibad8875de1e0bee8fe3a1dffb1add93111534cae Signed-off-by: Markus Duft <markus.duft@ssi-schaefer.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>stable-4.11
Markus Duft
7 years ago
committed by
Matthias Sohn
25 changed files with 848 additions and 93 deletions
@ -0,0 +1,140 @@
|
||||
/* |
||||
* Copyright (C) 2017, Markus Duft <markus.duft@ssi-schaefer.com> |
||||
* 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.lfs; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.PrintStream; |
||||
|
||||
import org.eclipse.jgit.annotations.Nullable; |
||||
import org.eclipse.jgit.attributes.Attribute; |
||||
import org.eclipse.jgit.hooks.PrePushHook; |
||||
import org.eclipse.jgit.lfs.lib.Constants; |
||||
import org.eclipse.jgit.lib.ConfigConstants; |
||||
import org.eclipse.jgit.lib.ObjectLoader; |
||||
import org.eclipse.jgit.lib.Repository; |
||||
import org.eclipse.jgit.util.LfsFactory; |
||||
|
||||
/** |
||||
* Implementation of {@link LfsFactory}, using built-in (optional) LFS support. |
||||
* |
||||
* @since 4.11 |
||||
*/ |
||||
public class BuiltinLFS extends LfsFactory { |
||||
|
||||
private BuiltinLFS() { |
||||
SmudgeFilter.register(); |
||||
CleanFilter.register(); |
||||
} |
||||
|
||||
/** |
||||
* Activates the built-in LFS support. |
||||
*/ |
||||
public static void register() { |
||||
setInstance(new BuiltinLFS()); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isAvailable() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public ObjectLoader applySmudgeFilter(Repository db, ObjectLoader loader, |
||||
Attribute attribute) throws IOException { |
||||
if (isEnabled(db) && (attribute == null || isEnabled(db, attribute))) { |
||||
return LfsBlobFilter.smudgeLfsBlob(db, loader); |
||||
} else { |
||||
return loader; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public LfsInputStream applyCleanFilter(Repository db, InputStream input, |
||||
long length, Attribute attribute) throws IOException { |
||||
if (isEnabled(db, attribute)) { |
||||
return new LfsInputStream(LfsBlobFilter.cleanLfsBlob(db, input)); |
||||
} else { |
||||
return new LfsInputStream(input, length); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public @Nullable PrePushHook getPrePushHook(Repository repo, |
||||
PrintStream outputStream) { |
||||
if (isEnabled(repo)) { |
||||
return new LfsPrePushHook(repo, outputStream); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* @param db |
||||
* the repository |
||||
* @return whether LFS is requested for the given repo. |
||||
*/ |
||||
private boolean isEnabled(Repository db) { |
||||
if (db == null) { |
||||
return false; |
||||
} |
||||
return db.getConfig().getBoolean(ConfigConstants.CONFIG_FILTER_SECTION, |
||||
Constants.LFS, ConfigConstants.CONFIG_KEY_USEJGITBUILTIN, |
||||
false); |
||||
} |
||||
|
||||
/** |
||||
* @param db |
||||
* the repository |
||||
* @param attribute |
||||
* the attribute to check |
||||
* @return whether LFS filter is enabled for the given .gitattribute |
||||
* attribute. |
||||
*/ |
||||
private boolean isEnabled(Repository db, Attribute attribute) { |
||||
if (attribute == null) { |
||||
return false; |
||||
} |
||||
return isEnabled(db) && Constants.LFS.equals(attribute.getValue()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,130 @@
|
||||
/* |
||||
* Copyright (C) 2017, Markus Duft <markus.duft@ssi-schaefer.com> |
||||
* 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.lfs; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
|
||||
import org.eclipse.jgit.lfs.lib.AnyLongObjectId; |
||||
import org.eclipse.jgit.lib.ObjectLoader; |
||||
import org.eclipse.jgit.lib.Repository; |
||||
import org.eclipse.jgit.util.TemporaryBuffer; |
||||
import org.eclipse.jgit.util.TemporaryBuffer.LocalFile; |
||||
|
||||
/** |
||||
* Provides transparently either a stream to the blob or a LFS media file if |
||||
* managed by LFS. |
||||
* |
||||
* @since 4.11 |
||||
*/ |
||||
public class LfsBlobFilter { |
||||
|
||||
/** |
||||
* In case the given {@link ObjectLoader} points to a LFS pointer file |
||||
* replace the loader with one pointing to the LFS media file contents. |
||||
* Missing LFS files are downloaded on the fly - same logic as the smudge |
||||
* filter. |
||||
* |
||||
* @param db |
||||
* the repo |
||||
* @param loader |
||||
* the loader for the blob |
||||
* @return either the original loader, or a loader for the LFS media file if |
||||
* managed by LFS. Files are downloaded on demand if required. |
||||
* @throws IOException |
||||
* in case of an error |
||||
*/ |
||||
public static ObjectLoader smudgeLfsBlob(Repository db, ObjectLoader loader) |
||||
throws IOException { |
||||
if (loader.getSize() > LfsPointer.SIZE_THRESHOLD) { |
||||
return loader; |
||||
} |
||||
|
||||
try (InputStream is = loader.openStream()) { |
||||
LfsPointer ptr = LfsPointer.parseLfsPointer(is); |
||||
if (ptr != null) { |
||||
Lfs lfs = new Lfs(db); |
||||
AnyLongObjectId oid = ptr.getOid(); |
||||
Path mediaFile = lfs.getMediaFile(oid); |
||||
if (!Files.exists(mediaFile)) { |
||||
SmudgeFilter.downloadLfsResource(lfs, db, ptr); |
||||
} |
||||
|
||||
return new LfsBlobLoader(mediaFile); |
||||
} |
||||
} |
||||
|
||||
return loader; |
||||
} |
||||
|
||||
/** |
||||
* Run the LFS clean filter on the given stream and return a stream to the |
||||
* LFS pointer file buffer. Used when inserting objects. |
||||
* |
||||
* @param db |
||||
* the {@link Repository} |
||||
* @param originalContent |
||||
* the {@link InputStream} to the original content |
||||
* @return a {@link TemporaryBuffer} representing the LFS pointer. The |
||||
* caller is responsible to destroy the buffer. |
||||
* @throws IOException |
||||
* in case of any error. |
||||
*/ |
||||
public static TemporaryBuffer cleanLfsBlob(Repository db, |
||||
InputStream originalContent) throws IOException { |
||||
LocalFile buffer = new TemporaryBuffer.LocalFile(null); |
||||
CleanFilter f = new CleanFilter(db, originalContent, buffer); |
||||
try { |
||||
while (f.run() != -1) { |
||||
// loop as long as f.run() tells there is work to do
|
||||
} |
||||
} catch (IOException e) { |
||||
buffer.destroy(); |
||||
throw e; |
||||
} |
||||
return buffer; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,119 @@
|
||||
/* |
||||
* Copyright (C) 2017, Markus Duft <markus.duft@ssi-schaefer.com> |
||||
* 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.lfs; |
||||
|
||||
import java.io.IOException; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.nio.file.attribute.BasicFileAttributes; |
||||
|
||||
import org.eclipse.jgit.errors.LargeObjectException; |
||||
import org.eclipse.jgit.errors.MissingObjectException; |
||||
import org.eclipse.jgit.lib.Constants; |
||||
import org.eclipse.jgit.lib.ObjectLoader; |
||||
import org.eclipse.jgit.lib.ObjectStream; |
||||
import org.eclipse.jgit.storage.pack.PackConfig; |
||||
import org.eclipse.jgit.util.IO; |
||||
|
||||
/** |
||||
* An {@link ObjectLoader} implementation that reads a media file from the LFS |
||||
* storage. |
||||
* |
||||
* @since 4.11 |
||||
*/ |
||||
public class LfsBlobLoader extends ObjectLoader { |
||||
|
||||
private Path mediaFile; |
||||
|
||||
private BasicFileAttributes attributes; |
||||
|
||||
private byte[] cached; |
||||
|
||||
/** |
||||
* Create a loader for the LFS media file at the given path. |
||||
* |
||||
* @param mediaFile |
||||
* path to the file |
||||
* @throws IOException |
||||
* in case of an error reading attributes |
||||
*/ |
||||
public LfsBlobLoader(Path mediaFile) throws IOException { |
||||
this.mediaFile = mediaFile; |
||||
this.attributes = Files.readAttributes(mediaFile, |
||||
BasicFileAttributes.class); |
||||
} |
||||
|
||||
@Override |
||||
public int getType() { |
||||
return Constants.OBJ_BLOB; |
||||
} |
||||
|
||||
@Override |
||||
public long getSize() { |
||||
return attributes.size(); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] getCachedBytes() throws LargeObjectException { |
||||
if (getSize() > PackConfig.DEFAULT_BIG_FILE_THRESHOLD) { |
||||
throw new LargeObjectException(); |
||||
} |
||||
|
||||
if (cached == null) { |
||||
try { |
||||
cached = IO.readFully(mediaFile.toFile()); |
||||
} catch (IOException ioe) { |
||||
throw new LargeObjectException(ioe); |
||||
} |
||||
} |
||||
return cached; |
||||
} |
||||
|
||||
@Override |
||||
public ObjectStream openStream() |
||||
throws MissingObjectException, IOException { |
||||
return new ObjectStream.Filter(getType(), getSize(), |
||||
Files.newInputStream(mediaFile)); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,284 @@
|
||||
/* |
||||
* Copyright (C) 2018, Markus Duft <markus.duft@ssi-schaefer.com> |
||||
* 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.util; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.PrintStream; |
||||
import java.text.MessageFormat; |
||||
|
||||
import org.eclipse.jgit.annotations.Nullable; |
||||
import org.eclipse.jgit.attributes.Attribute; |
||||
import org.eclipse.jgit.attributes.Attributes; |
||||
import org.eclipse.jgit.hooks.PrePushHook; |
||||
import org.eclipse.jgit.internal.JGitText; |
||||
import org.eclipse.jgit.lib.ObjectLoader; |
||||
import org.eclipse.jgit.lib.Repository; |
||||
import org.eclipse.jgit.revwalk.RevCommit; |
||||
import org.eclipse.jgit.treewalk.FileTreeIterator; |
||||
import org.eclipse.jgit.treewalk.TreeWalk; |
||||
import org.eclipse.jgit.treewalk.filter.PathFilter; |
||||
|
||||
/** |
||||
* Represents an optionally present LFS support implementation |
||||
* |
||||
* @since 4.11 |
||||
*/ |
||||
public class LfsFactory { |
||||
|
||||
private static LfsFactory instance = new LfsFactory(); |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
protected LfsFactory() { |
||||
} |
||||
|
||||
/** |
||||
* @return the current LFS implementation |
||||
*/ |
||||
public static LfsFactory getInstance() { |
||||
return instance; |
||||
} |
||||
|
||||
/** |
||||
* @param instance |
||||
* register a {@link LfsFactory} instance as the |
||||
* {@link LfsFactory} implementation to use. |
||||
*/ |
||||
public static void setInstance(LfsFactory instance) { |
||||
LfsFactory.instance = instance; |
||||
} |
||||
|
||||
/** |
||||
* @return whether LFS support is available |
||||
*/ |
||||
public boolean isAvailable() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Apply clean filtering to the given stream, writing the file content to |
||||
* the LFS storage if required and returning a stream to the LFS pointer |
||||
* instead. |
||||
* |
||||
* @param db |
||||
* the repository |
||||
* @param input |
||||
* the original input |
||||
* @param length |
||||
* the expected input stream length |
||||
* @param attribute |
||||
* the attribute used to check for LFS enablement (i.e. "merge", |
||||
* "diff", "filter" from .gitattributes). |
||||
* @return a stream to the content that should be written to the object |
||||
* store along with the expected length of the stream. the original |
||||
* stream is not applicable. |
||||
* @throws IOException |
||||
* in case of an error |
||||
*/ |
||||
public LfsInputStream applyCleanFilter(Repository db, |
||||
InputStream input, long length, Attribute attribute) |
||||
throws IOException { |
||||
return new LfsInputStream(input, length); |
||||
} |
||||
|
||||
/** |
||||
* Apply smudge filtering to a given loader, potentially redirecting it to a |
||||
* LFS blob which is downloaded on demand. |
||||
* |
||||
* @param db |
||||
* the repository |
||||
* @param loader |
||||
* the loader for the blob |
||||
* @param attribute |
||||
* the attribute used to check for LFS enablement (i.e. "merge", |
||||
* "diff", "filter" from .gitattributes). |
||||
* @return a loader for the actual data of a blob, or the original loader in |
||||
* case LFS is not applicable. |
||||
* @throws IOException |
||||
*/ |
||||
public ObjectLoader applySmudgeFilter(Repository db, |
||||
ObjectLoader loader, Attribute attribute) throws IOException { |
||||
return loader; |
||||
} |
||||
|
||||
/** |
||||
* Retrieve a pre-push hook to be applied. |
||||
* |
||||
* @param repo |
||||
* the {@link Repository} the hook is applied to. |
||||
* @param outputStream |
||||
* @return a {@link PrePushHook} implementation or <code>null</code> |
||||
*/ |
||||
public @Nullable PrePushHook getPrePushHook(Repository repo, |
||||
PrintStream outputStream) { |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* @param db |
||||
* the repository |
||||
* @param path |
||||
* the path to find attributes for |
||||
* @return the {@link Attributes} for the given path. |
||||
* @throws IOException |
||||
* in case of an error |
||||
*/ |
||||
public static Attributes getAttributesForPath(Repository db, String path) |
||||
throws IOException { |
||||
try (TreeWalk walk = new TreeWalk(db)) { |
||||
walk.addTree(new FileTreeIterator(db)); |
||||
PathFilter f = PathFilter.create(path); |
||||
walk.setFilter(f); |
||||
walk.setRecursive(false); |
||||
Attributes attr = null; |
||||
while (walk.next()) { |
||||
if (f.isDone(walk)) { |
||||
attr = walk.getAttributes(); |
||||
break; |
||||
} else if (walk.isSubtree()) { |
||||
walk.enterSubtree(); |
||||
} |
||||
} |
||||
if (attr == null) { |
||||
throw new IOException(MessageFormat |
||||
.format(JGitText.get().noPathAttributesFound, path)); |
||||
} |
||||
|
||||
return attr; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get attributes for given path and commit |
||||
* |
||||
* @param db |
||||
* the repository |
||||
* @param path |
||||
* the path to find attributes for |
||||
* @param commit |
||||
* the commit to inspect. |
||||
* @return the {@link Attributes} for the given path. |
||||
* @throws IOException |
||||
* in case of an error |
||||
*/ |
||||
public static Attributes getAttributesForPath(Repository db, String path, |
||||
RevCommit commit) throws IOException { |
||||
if (commit == null) { |
||||
return getAttributesForPath(db, path); |
||||
} |
||||
|
||||
try (TreeWalk walk = TreeWalk.forPath(db, path, commit.getTree())) { |
||||
Attributes attr = walk == null ? null : walk.getAttributes(); |
||||
if (attr == null) { |
||||
throw new IOException(MessageFormat |
||||
.format(JGitText.get().noPathAttributesFound, path)); |
||||
} |
||||
|
||||
return attr; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Encapsulate a potentially exchanged {@link InputStream} along with the |
||||
* expected stream content length. |
||||
*/ |
||||
public static final class LfsInputStream extends InputStream { |
||||
/** |
||||
* The actual stream. |
||||
*/ |
||||
private InputStream stream; |
||||
|
||||
/** |
||||
* The expected stream content length. |
||||
*/ |
||||
private long length; |
||||
|
||||
/** |
||||
* Create a new wrapper around a certain stream |
||||
* |
||||
* @param stream |
||||
* the stream to wrap. the stream will be closed on |
||||
* {@link #close()}. |
||||
* @param length |
||||
* the expected length of the stream |
||||
*/ |
||||
public LfsInputStream(InputStream stream, long length) { |
||||
this.stream = stream; |
||||
this.length = length; |
||||
} |
||||
|
||||
/** |
||||
* Create a new wrapper around a temporary buffer. |
||||
* |
||||
* @param buffer |
||||
* the buffer to initialize stream and length from. The |
||||
* buffer will be destroyed on {@link #close()} |
||||
* @throws IOException |
||||
* in case of an error opening the stream to the buffer. |
||||
*/ |
||||
public LfsInputStream(TemporaryBuffer buffer) throws IOException { |
||||
this.stream = buffer.openInputStream(); |
||||
this.length = buffer.length(); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
stream.close(); |
||||
} |
||||
|
||||
@Override |
||||
public int read() throws IOException { |
||||
return stream.read(); |
||||
} |
||||
|
||||
/** |
||||
* @return the length of the stream |
||||
*/ |
||||
public long getLength() { |
||||
return length; |
||||
} |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue