From 83555e7e303b45b9a96fbae4a7ebbff3cdb83b1c Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Wed, 26 Oct 2016 22:33:49 +0200 Subject: [PATCH] Use AtomicObjectOutputStream in CleanFilter Enhance and use AtomicObjectOutputStream to write temporary files in CleanFilter. Change-Id: I28987dad18255a9067344f94b4e836cbd183e4b1 Signed-off-by: Matthias Sohn --- .../src/org/eclipse/jgit/lfs/CleanFilter.java | 32 +++++++------------ .../internal/AtomicObjectOutputStream.java | 23 ++++++++++++- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java index fa5c74ccd9..66feca7518 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java @@ -48,15 +48,13 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; -import java.security.DigestOutputStream; import org.eclipse.jgit.attributes.FilterCommand; import org.eclipse.jgit.attributes.FilterCommandFactory; import org.eclipse.jgit.attributes.FilterCommandRegistry; import org.eclipse.jgit.lfs.errors.CorruptMediaFile; -import org.eclipse.jgit.lfs.lib.Constants; -import org.eclipse.jgit.lfs.lib.LongObjectId; +import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream; +import org.eclipse.jgit.lfs.lib.AnyLongObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.util.FileUtils; @@ -98,12 +96,8 @@ public class CleanFilter extends FilterCommand { FACTORY); } - // The OutputStream to a temporary file which will be renamed to mediafile - // when the operation succeeds - private OutputStream tmpOut; - // Used to compute the hash for the original content - private DigestOutputStream dOut; + private AtomicObjectOutputStream aOut; private Lfs lfsUtil; @@ -133,11 +127,7 @@ public class CleanFilter extends FilterCommand { lfsUtil = new Lfs(db.getDirectory().toPath().resolve("lfs")); //$NON-NLS-1$ Files.createDirectories(lfsUtil.getLfsTmpDir()); tmpFile = lfsUtil.createTmpFile(); - tmpOut = Files.newOutputStream(tmpFile, - StandardOpenOption.CREATE); - this.dOut = new DigestOutputStream( - tmpOut, - Constants.newMessageDigest()); + this.aOut = new AtomicObjectOutputStream(tmpFile.toAbsolutePath()); } public int run() throws IOException { @@ -145,14 +135,13 @@ public class CleanFilter extends FilterCommand { byte[] buf = new byte[8192]; int length = in.read(buf); if (length != -1) { - dOut.write(buf, 0, length); + aOut.write(buf, 0, length); size += length; return length; } else { - dOut.close(); - tmpOut.close(); - LongObjectId loid = LongObjectId - .fromRaw(dOut.getMessageDigest().digest()); + aOut.close(); + AnyLongObjectId loid = aOut.getId(); + aOut = null; Path mediaFile = lfsUtil.getMediaFile(loid); if (Files.isRegularFile(mediaFile)) { long fsSize = Files.size(mediaFile); @@ -172,9 +161,10 @@ public class CleanFilter extends FilterCommand { return -1; } } catch (IOException e) { + if (aOut != null) { + aOut.abort(); + } out.close(); - dOut.close(); - tmpOut.close(); throw e; } } diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java index 7e050b1e78..867cca5056 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java @@ -48,6 +48,7 @@ import java.nio.file.Path; import java.security.DigestOutputStream; import java.text.MessageFormat; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.storage.file.LockFile; import org.eclipse.jgit.lfs.errors.CorruptLongObjectException; import org.eclipse.jgit.lfs.lib.AnyLongObjectId; @@ -83,6 +84,22 @@ public class AtomicObjectOutputStream extends OutputStream { Constants.newMessageDigest()); } + /** + * @param path + * @throws IOException + */ + public AtomicObjectOutputStream(Path path) throws IOException { + this(path, null); + } + + /** + * @return content hash of the object which was streamed through this + * stream. May return {@code null} if called before closing this stream. + */ + public @Nullable AnyLongObjectId getId() { + return id; + } + @Override public void write(int b) throws IOException { out.write(b); @@ -102,7 +119,11 @@ public class AtomicObjectOutputStream extends OutputStream { public void close() throws IOException { out.close(); if (!aborted) { - verifyHash(); + if (id != null) { + verifyHash(); + } else { + id = LongObjectId.fromRaw(out.getMessageDigest().digest()); + } locked.commit(); } } -- 2.39.5