1 package org
.spearce
.jgit
.lib
;
3 import java
.io
.ByteArrayInputStream
;
4 import java
.io
.ByteArrayOutputStream
;
6 import java
.io
.FileInputStream
;
7 import java
.io
.FileOutputStream
;
8 import java
.io
.IOException
;
9 import java
.io
.InputStream
;
10 import java
.io
.UnsupportedEncodingException
;
11 import java
.security
.MessageDigest
;
12 import java
.security
.NoSuchAlgorithmException
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Collections
;
15 import java
.util
.Iterator
;
16 import java
.util
.zip
.DeflaterOutputStream
;
18 public class WriteTree
extends TreeVisitor
{
19 private static final TreeNameComparator TNC
= new TreeNameComparator();
21 private static final byte[] TREE_MODE
;
23 private static final byte[] SYMLINK_MODE
;
25 private static final byte[] PLAIN_FILE_MODE
;
27 private static final byte[] EXECUTABLE_FILE_MODE
;
31 TREE_MODE
= "40000".getBytes("UTF-8");
32 SYMLINK_MODE
= "120000".getBytes("UTF-8");
33 PLAIN_FILE_MODE
= "100644".getBytes("UTF-8");
34 EXECUTABLE_FILE_MODE
= "100755".getBytes("UTF-8");
35 } catch (UnsupportedEncodingException uue
) {
36 throw new ExceptionInInitializerError(uue
);
40 private final ObjectDatabase objdb
;
42 private final byte[] copybuf
;
44 private final MessageDigest md
;
46 private final boolean writeAll
;
50 public WriteTree(final ObjectDatabase db
, final File sourceDir
)
51 throws NoSuchAlgorithmException
{
53 copybuf
= new byte[8192];
54 md
= MessageDigest
.getInstance("SHA-1");
59 protected void visitFile(final FileTreeEntry f
) throws IOException
{
61 final File d
= new File(src
, f
.getName());
62 final FileInputStream is
= new FileInputStream(d
);
64 f
.setId(writeObject("blob", (int) d
.length(), is
));
70 protected void visitSymlink(final SymlinkTreeEntry s
) throws IOException
{
71 super.visitSymlink(s
);
73 if (!objdb
.checkObject(s
.getId())) {
74 throw new CorruptObjectException("Missing symlink blob "
79 protected void visitTree(final Tree t
) throws IOException
{
80 // Only visit a tree if it has been modified. If any child of a tree has
81 // been modified then the tree itself will also appear modified;
82 // consequently we will recurse into it.
84 if (writeAll
|| t
.isModified()) {
88 final File d
= new File(src
, t
.getName());
95 final ByteArrayOutputStream o
= new ByteArrayOutputStream();
96 final ArrayList r
= new ArrayList();
100 i
= t
.entryIterator();
101 while (i
.hasNext()) {
104 Collections
.sort(r
, TNC
);
107 while (i
.hasNext()) {
108 final TreeEntry e
= (TreeEntry
) i
.next();
111 if (e
instanceof Tree
) {
113 } else if (e
instanceof SymlinkTreeEntry
) {
115 } else if (e
instanceof FileTreeEntry
) {
116 mode
= ((FileTreeEntry
) e
).isExecutable() ? EXECUTABLE_FILE_MODE
119 throw new IOException("Object not supported in Tree:" + e
);
124 o
.write(e
.getNameUTF8());
126 o
.write(e
.getId().getBytes());
129 t
.setId(writeObject("tree", d
.length
, new ByteArrayInputStream(d
)));
133 private ObjectId
writeObject(final String type
, int len
,
134 final InputStream is
) throws IOException
{
135 final File t
= File
.createTempFile("noz", null, objdb
136 .getObjectsDirectory());
137 final DeflaterOutputStream ts
= new DeflaterOutputStream(
138 new FileOutputStream(t
));
141 final byte[] header
= (type
+ " " + len
+ "\0").getBytes("UTF-8");
147 while ((r
= is
.read(copybuf
)) > 0 && len
> 0) {
151 md
.update(copybuf
, 0, r
);
152 ts
.write(copybuf
, 0, r
);
156 throw new CorruptObjectException("Input was short: " + len
);
160 id
= new ObjectId(md
.digest());
169 if (objdb
.checkObject(id
)) {
170 // Object is already in the repository so remove the temporary file.
174 final File o
= objdb
.objectFile(id
);
175 o
.getParentFile().mkdir();
176 if (!t
.renameTo(o
)) {
177 if (!objdb
.checkObject(id
)) {
178 // The object failed to be renamed into its proper location
179 // and it doesn't exist in the repository either. (The
180 // rename could have failed if another process was placing
181 // the object there at the same time as us.) We really don't
182 // know what went wrong, so abort.
185 throw new IOException("Failed to write object " + id
);