1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.lfs.server.fs;
44
45 import static org.eclipse.jgit.util.HttpSupport.HDR_AUTHORIZATION;
46
47 import java.io.IOException;
48 import java.nio.channels.FileChannel;
49 import java.nio.channels.ReadableByteChannel;
50 import java.nio.file.Files;
51 import java.nio.file.Path;
52 import java.nio.file.StandardOpenOption;
53 import java.util.Collections;
54
55 import org.eclipse.jgit.annotations.Nullable;
56 import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream;
57 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
58 import org.eclipse.jgit.lfs.lib.Constants;
59 import org.eclipse.jgit.lfs.server.LargeFileRepository;
60 import org.eclipse.jgit.lfs.server.Response;
61 import org.eclipse.jgit.lfs.server.Response.Action;
62
63
64
65
66
67
68 public class FileLfsRepository implements LargeFileRepository {
69
70 private String url;
71 private final Path dir;
72
73
74
75
76
77
78
79
80
81
82 public FileLfsRepository(String url, Path dir) throws IOException {
83 this.url = url;
84 this.dir = dir;
85 Files.createDirectories(dir);
86 }
87
88
89 @Override
90 public Response.Action getDownloadAction(AnyLongObjectId id) {
91 return getAction(id);
92 }
93
94
95 @Override
96 public Action getUploadAction(AnyLongObjectId id, long size) {
97 return getAction(id);
98 }
99
100
101 @Override
102 @Nullable
103 public Action getVerifyAction(AnyLongObjectId id) {
104 return null;
105 }
106
107
108 @Override
109 public long getSize(AnyLongObjectId id) throws IOException {
110 Path p = getPath(id);
111 if (Files.exists(p)) {
112 return Files.size(p);
113 }
114 return -1;
115 }
116
117
118
119
120
121
122 public Path getDir() {
123 return dir;
124 }
125
126
127
128
129
130
131
132
133 protected Path getPath(AnyLongObjectId id) {
134 StringBuilder s = new StringBuilder(
135 Constants.LONG_OBJECT_ID_STRING_LENGTH + 6);
136 s.append(toHexCharArray(id.getFirstByte())).append('/');
137 s.append(toHexCharArray(id.getSecondByte())).append('/');
138 s.append(id.name());
139 return dir.resolve(s.toString());
140 }
141
142 private Response.Action getAction(AnyLongObjectId id) {
143 Response.Action a = new Response.Action();
144 a.href = url + id.getName();
145 a.header = Collections.singletonMap(HDR_AUTHORIZATION, "not:required");
146 return a;
147 }
148
149 ReadableByteChannel getReadChannel(AnyLongObjectId id)
150 throws IOException {
151 return FileChannel.open(getPath(id), StandardOpenOption.READ);
152 }
153
154 AtomicObjectOutputStream getOutputStream(AnyLongObjectId id)
155 throws IOException {
156 Path path = getPath(id);
157 Path parent = path.getParent();
158 if (parent != null) {
159 Files.createDirectories(parent);
160 }
161 return new AtomicObjectOutputStream(path, id);
162 }
163
164 private static char[] toHexCharArray(int b) {
165 final char[] dst = new char[2];
166 formatHexChar(dst, 0, b);
167 return dst;
168 }
169
170 private static final char[] hexchar = { '0', '1', '2', '3', '4', '5', '6',
171 '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
172
173 private static void formatHexChar(char[] dst, int p, int b) {
174 int o = p + 1;
175 while (o >= p && b != 0) {
176 dst[o--] = hexchar[b & 0xf];
177 b >>>= 4;
178 }
179 while (o >= p)
180 dst[o--] = '0';
181 }
182
183
184
185
186
187 public String getUrl() {
188 return url;
189 }
190
191
192
193
194
195
196 public void setUrl(String url) {
197 this.url = url;
198 }
199 }