1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.lfs.internal;
11
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.nio.file.Path;
15 import java.security.DigestOutputStream;
16 import java.text.MessageFormat;
17
18 import org.eclipse.jgit.annotations.Nullable;
19 import org.eclipse.jgit.internal.storage.file.LockFile;
20 import org.eclipse.jgit.lfs.errors.CorruptLongObjectException;
21 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
22 import org.eclipse.jgit.lfs.lib.Constants;
23 import org.eclipse.jgit.lfs.lib.LongObjectId;
24
25
26
27
28
29
30 public class AtomicObjectOutputStream extends OutputStream {
31
32 private LockFile locked;
33
34 private DigestOutputStream out;
35
36 private boolean aborted;
37
38 private AnyLongObjectId id;
39
40
41
42
43
44
45
46
47
48
49 public AtomicObjectOutputStream(Path path, AnyLongObjectId id)
50 throws IOException {
51 locked = new LockFile(path.toFile());
52 locked.lock();
53 this.id = id;
54 out = new DigestOutputStream(locked.getOutputStream(),
55 Constants.newMessageDigest());
56 }
57
58
59
60
61
62
63
64
65 public AtomicObjectOutputStream(Path path) throws IOException {
66 this(path, null);
67 }
68
69
70
71
72
73
74
75
76 @Nullable
77 public AnyLongObjectId getId() {
78 return id;
79 }
80
81
82 @Override
83 public void write(int b) throws IOException {
84 out.write(b);
85 }
86
87
88 @Override
89 public void write(byte[] b) throws IOException {
90 out.write(b);
91 }
92
93
94 @Override
95 public void write(byte[] b, int off, int len) throws IOException {
96 out.write(b, off, len);
97 }
98
99
100 @Override
101 public void close() throws IOException {
102 out.close();
103 if (!aborted) {
104 if (id != null) {
105 verifyHash();
106 } else {
107 id = LongObjectId.fromRaw(out.getMessageDigest().digest());
108 }
109 locked.commit();
110 }
111 }
112
113 private void verifyHash() {
114 AnyLongObjectId contentHash = LongObjectId
115 .fromRaw(out.getMessageDigest().digest());
116 if (!contentHash.equals(id)) {
117 abort();
118 throw new CorruptLongObjectException(id, contentHash,
119 MessageFormat.format(LfsText.get().corruptLongObject,
120 contentHash, id));
121 }
122 }
123
124
125
126
127 public void abort() {
128 locked.unlock();
129 aborted = true;
130 }
131 }