@@ -2,7 +2,7 @@
|
|
2 |
<classpath>
|
3 |
<classpathentry kind="src" path="src"/>
|
4 |
<classpathentry kind="src" path="resources"/>
|
5 |
-
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-
|
6 |
<attributes>
|
7 |
<attribute name="module" value="true"/>
|
8 |
</attributes>
|
|
|
2 |
<classpath>
|
3 |
<classpathentry kind="src" path="src"/>
|
4 |
<classpathentry kind="src" path="resources"/>
|
5 |
+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
|
6 |
<attributes>
|
7 |
<attribute name="module" value="true"/>
|
8 |
</attributes>
|
@@ -7,9 +7,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jgit.annotations.N
|
|
7 |
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
|
8 |
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
9 |
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
10 |
-
org.eclipse.jdt.core.compiler.codegen.targetPlatform=
|
11 |
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
12 |
-
org.eclipse.jdt.core.compiler.compliance=
|
13 |
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
14 |
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
15 |
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
@@ -115,7 +115,7 @@ org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
|
115 |
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
116 |
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
|
117 |
org.eclipse.jdt.core.compiler.release=enabled
|
118 |
-
org.eclipse.jdt.core.compiler.source=
|
119 |
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
120 |
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
121 |
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
|
|
7 |
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
|
8 |
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
9 |
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
10 |
+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
|
11 |
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
12 |
+
org.eclipse.jdt.core.compiler.compliance=17
|
13 |
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
14 |
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
15 |
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
|
|
115 |
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
116 |
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
|
117 |
org.eclipse.jdt.core.compiler.release=enabled
|
118 |
+
org.eclipse.jdt.core.compiler.source=17
|
119 |
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
120 |
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
121 |
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
@@ -3,14 +3,14 @@ Bundle-ManifestVersion: 2
|
|
3 |
Bundle-Name: %Bundle-Name
|
4 |
Automatic-Module-Name: org.eclipse.jgit
|
5 |
Bundle-SymbolicName: org.eclipse.jgit
|
6 |
-
Bundle-Version:
|
7 |
Bundle-Localization: OSGI-INF/l10n/plugin
|
8 |
Bundle-Vendor: %Bundle-Vendor
|
9 |
Bundle-ActivationPolicy: lazy
|
10 |
Service-Component: OSGI-INF/org.eclipse.jgit.internal.util.CleanupService.xml
|
11 |
Eclipse-ExtensibleAPI: true
|
12 |
-
Export-Package: org.eclipse.jgit.annotations;version="
|
13 |
-
org.eclipse.jgit.api;version="
|
14 |
uses:="org.eclipse.jgit.transport,
|
15 |
org.eclipse.jgit.notes,
|
16 |
org.eclipse.jgit.dircache,
|
@@ -25,18 +25,18 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
25 |
org.eclipse.jgit.revwalk.filter,
|
26 |
org.eclipse.jgit.blame,
|
27 |
org.eclipse.jgit.merge",
|
28 |
-
org.eclipse.jgit.api.errors;version="
|
29 |
uses:="org.eclipse.jgit.lib,
|
30 |
org.eclipse.jgit.errors",
|
31 |
-
org.eclipse.jgit.attributes;version="
|
32 |
uses:="org.eclipse.jgit.lib,
|
33 |
org.eclipse.jgit.treewalk",
|
34 |
-
org.eclipse.jgit.blame;version="
|
35 |
uses:="org.eclipse.jgit.lib,
|
36 |
org.eclipse.jgit.revwalk,
|
37 |
org.eclipse.jgit.treewalk.filter,
|
38 |
org.eclipse.jgit.diff",
|
39 |
-
org.eclipse.jgit.diff;version="
|
40 |
uses:="org.eclipse.jgit.lib,
|
41 |
org.eclipse.jgit.attributes,
|
42 |
org.eclipse.jgit.revwalk,
|
@@ -44,53 +44,53 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
44 |
org.eclipse.jgit.treewalk.filter,
|
45 |
org.eclipse.jgit.treewalk,
|
46 |
org.eclipse.jgit.util",
|
47 |
-
org.eclipse.jgit.dircache;version="
|
48 |
uses:="org.eclipse.jgit.events,
|
49 |
org.eclipse.jgit.lib,
|
50 |
org.eclipse.jgit.attributes,
|
51 |
org.eclipse.jgit.treewalk,
|
52 |
org.eclipse.jgit.util",
|
53 |
-
org.eclipse.jgit.errors;version="
|
54 |
uses:="org.eclipse.jgit.transport,
|
55 |
org.eclipse.jgit.dircache,
|
56 |
org.eclipse.jgit.lib,
|
57 |
org.eclipse.jgit.internal.storage.pack",
|
58 |
-
org.eclipse.jgit.events;version="
|
59 |
uses:="org.eclipse.jgit.lib",
|
60 |
-
org.eclipse.jgit.fnmatch;version="
|
61 |
-
org.eclipse.jgit.gitrepo;version="
|
62 |
uses:="org.xml.sax.helpers,
|
63 |
org.eclipse.jgit.api,
|
64 |
org.eclipse.jgit.lib,
|
65 |
org.eclipse.jgit.revwalk,
|
66 |
org.xml.sax",
|
67 |
-
org.eclipse.jgit.gitrepo.internal;version="
|
68 |
-
org.eclipse.jgit.hooks;version="
|
69 |
-
org.eclipse.jgit.ignore;version="
|
70 |
-
org.eclipse.jgit.ignore.internal;version="
|
71 |
x-friends:="org.eclipse.jgit.test",
|
72 |
-
org.eclipse.jgit.internal;version="
|
73 |
x-friends:="org.eclipse.jgit.test,
|
74 |
org.eclipse.jgit.http.test",
|
75 |
-
org.eclipse.jgit.internal.diff;version="
|
76 |
x-friends:="org.eclipse.jgit.test",
|
77 |
-
org.eclipse.jgit.internal.diffmergetool;version="
|
78 |
x-friends:="org.eclipse.jgit.test,
|
79 |
org.eclipse.jgit.pgm.test,
|
80 |
org.eclipse.jgit.pgm,
|
81 |
org.eclipse.egit.ui",
|
82 |
-
org.eclipse.jgit.internal.fsck;version="
|
83 |
x-friends:="org.eclipse.jgit.test",
|
84 |
-
org.eclipse.jgit.internal.revwalk;version="
|
85 |
x-friends:="org.eclipse.jgit.test",
|
86 |
-
org.eclipse.jgit.internal.storage.commitgraph;version="
|
87 |
x-friends:="org.eclipse.jgit.test",
|
88 |
-
org.eclipse.jgit.internal.storage.dfs;version="
|
89 |
x-friends:="org.eclipse.jgit.test,
|
90 |
org.eclipse.jgit.http.server,
|
91 |
org.eclipse.jgit.http.test,
|
92 |
org.eclipse.jgit.lfs.test",
|
93 |
-
org.eclipse.jgit.internal.storage.file;version="
|
94 |
x-friends:="org.eclipse.jgit.test,
|
95 |
org.eclipse.jgit.junit,
|
96 |
org.eclipse.jgit.junit.http,
|
@@ -99,36 +99,36 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
99 |
org.eclipse.jgit.pgm,
|
100 |
org.eclipse.jgit.pgm.test,
|
101 |
org.eclipse.jgit.ssh.apache",
|
102 |
-
org.eclipse.jgit.internal.storage.io;version="
|
103 |
x-friends:="org.eclipse.jgit.junit,
|
104 |
org.eclipse.jgit.test,
|
105 |
org.eclipse.jgit.pgm",
|
106 |
-
org.eclipse.jgit.internal.storage.memory;version="
|
107 |
x-friends:="org.eclipse.jgit.test",
|
108 |
-
org.eclipse.jgit.internal.storage.pack;version="
|
109 |
x-friends:="org.eclipse.jgit.junit,
|
110 |
org.eclipse.jgit.test,
|
111 |
org.eclipse.jgit.pgm",
|
112 |
-
org.eclipse.jgit.internal.storage.reftable;version="
|
113 |
x-friends:="org.eclipse.jgit.http.test,
|
114 |
org.eclipse.jgit.junit,
|
115 |
org.eclipse.jgit.test,
|
116 |
org.eclipse.jgit.pgm",
|
117 |
-
org.eclipse.jgit.internal.submodule;version="
|
118 |
-
org.eclipse.jgit.internal.transport.connectivity;version="
|
119 |
x-friends:="org.eclipse.jgit.test",
|
120 |
-
org.eclipse.jgit.internal.transport.http;version="
|
121 |
x-friends:="org.eclipse.jgit.test",
|
122 |
-
org.eclipse.jgit.internal.transport.parser;version="
|
123 |
x-friends:="org.eclipse.jgit.http.server,
|
124 |
org.eclipse.jgit.test",
|
125 |
-
org.eclipse.jgit.internal.transport.ssh;version="
|
126 |
x-friends:="org.eclipse.jgit.ssh.apache,
|
127 |
org.eclipse.jgit.ssh.jsch,
|
128 |
org.eclipse.jgit.test",
|
129 |
-
org.eclipse.jgit.internal.util;version="
|
130 |
x-friends:=" org.eclipse.jgit.junit",
|
131 |
-
org.eclipse.jgit.lib;version="
|
132 |
uses:="org.eclipse.jgit.transport,
|
133 |
org.eclipse.jgit.util.sha1,
|
134 |
org.eclipse.jgit.dircache,
|
@@ -142,12 +142,12 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
142 |
org.eclipse.jgit.util,
|
143 |
org.eclipse.jgit.submodule,
|
144 |
org.eclipse.jgit.util.time",
|
145 |
-
org.eclipse.jgit.lib.internal;version="
|
146 |
x-friends:="org.eclipse.jgit.test,
|
147 |
org.eclipse.jgit.pgm,
|
148 |
org.eclipse.egit.ui",
|
149 |
-
org.eclipse.jgit.logging;version="
|
150 |
-
org.eclipse.jgit.merge;version="
|
151 |
uses:="org.eclipse.jgit.dircache,
|
152 |
org.eclipse.jgit.lib,
|
153 |
org.eclipse.jgit.revwalk,
|
@@ -156,40 +156,40 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
156 |
org.eclipse.jgit.util,
|
157 |
org.eclipse.jgit.api,
|
158 |
org.eclipse.jgit.attributes",
|
159 |
-
org.eclipse.jgit.nls;version="
|
160 |
-
org.eclipse.jgit.notes;version="
|
161 |
uses:="org.eclipse.jgit.lib,
|
162 |
org.eclipse.jgit.revwalk,
|
163 |
org.eclipse.jgit.treewalk,
|
164 |
org.eclipse.jgit.merge",
|
165 |
-
org.eclipse.jgit.patch;version="
|
166 |
uses:="org.eclipse.jgit.lib,
|
167 |
org.eclipse.jgit.diff",
|
168 |
-
org.eclipse.jgit.revplot;version="
|
169 |
uses:="org.eclipse.jgit.lib,
|
170 |
org.eclipse.jgit.revwalk",
|
171 |
-
org.eclipse.jgit.revwalk;version="
|
172 |
uses:="org.eclipse.jgit.lib,
|
173 |
org.eclipse.jgit.diff,
|
174 |
org.eclipse.jgit.treewalk.filter,
|
175 |
org.eclipse.jgit.revwalk.filter,
|
176 |
org.eclipse.jgit.treewalk",
|
177 |
-
org.eclipse.jgit.revwalk.filter;version="
|
178 |
uses:="org.eclipse.jgit.revwalk,
|
179 |
org.eclipse.jgit.lib,
|
180 |
org.eclipse.jgit.util",
|
181 |
-
org.eclipse.jgit.storage.file;version="
|
182 |
uses:="org.eclipse.jgit.lib,
|
183 |
org.eclipse.jgit.util",
|
184 |
-
org.eclipse.jgit.storage.pack;version="
|
185 |
uses:="org.eclipse.jgit.lib",
|
186 |
-
org.eclipse.jgit.submodule;version="
|
187 |
uses:="org.eclipse.jgit.lib,
|
188 |
org.eclipse.jgit.diff,
|
189 |
org.eclipse.jgit.treewalk.filter,
|
190 |
org.eclipse.jgit.treewalk,
|
191 |
org.eclipse.jgit.util",
|
192 |
-
org.eclipse.jgit.transport;version="
|
193 |
uses:="javax.crypto,
|
194 |
org.eclipse.jgit.util.io,
|
195 |
org.eclipse.jgit.lib,
|
@@ -202,21 +202,21 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
202 |
org.eclipse.jgit.transport.resolver,
|
203 |
org.eclipse.jgit.storage.pack,
|
204 |
org.eclipse.jgit.errors",
|
205 |
-
org.eclipse.jgit.transport.http;version="
|
206 |
uses:="javax.net.ssl",
|
207 |
-
org.eclipse.jgit.transport.resolver;version="
|
208 |
uses:="org.eclipse.jgit.transport,
|
209 |
org.eclipse.jgit.lib",
|
210 |
-
org.eclipse.jgit.treewalk;version="
|
211 |
uses:="org.eclipse.jgit.dircache,
|
212 |
org.eclipse.jgit.lib,
|
213 |
org.eclipse.jgit.attributes,
|
214 |
org.eclipse.jgit.revwalk,
|
215 |
org.eclipse.jgit.treewalk.filter,
|
216 |
org.eclipse.jgit.util",
|
217 |
-
org.eclipse.jgit.treewalk.filter;version="
|
218 |
uses:="org.eclipse.jgit.treewalk",
|
219 |
-
org.eclipse.jgit.util;version="
|
220 |
uses:="org.eclipse.jgit.transport,
|
221 |
org.eclipse.jgit.hooks,
|
222 |
org.eclipse.jgit.revwalk,
|
@@ -229,13 +229,13 @@ Export-Package: org.eclipse.jgit.annotations;version="6.10.0",
|
|
229 |
org.eclipse.jgit.treewalk,
|
230 |
javax.net.ssl,
|
231 |
org.eclipse.jgit.util.time",
|
232 |
-
org.eclipse.jgit.util.io;version="
|
233 |
uses:="org.eclipse.jgit.attributes,
|
234 |
org.eclipse.jgit.lib,
|
235 |
org.eclipse.jgit.treewalk",
|
236 |
-
org.eclipse.jgit.util.sha1;version="
|
237 |
-
org.eclipse.jgit.util.time;version="
|
238 |
-
Bundle-RequiredExecutionEnvironment: JavaSE-
|
239 |
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
|
240 |
javax.crypto,
|
241 |
javax.management,
|
|
|
3 |
Bundle-Name: %Bundle-Name
|
4 |
Automatic-Module-Name: org.eclipse.jgit
|
5 |
Bundle-SymbolicName: org.eclipse.jgit
|
6 |
+
Bundle-Version: 7.0.0.202409031743-r
|
7 |
Bundle-Localization: OSGI-INF/l10n/plugin
|
8 |
Bundle-Vendor: %Bundle-Vendor
|
9 |
Bundle-ActivationPolicy: lazy
|
10 |
Service-Component: OSGI-INF/org.eclipse.jgit.internal.util.CleanupService.xml
|
11 |
Eclipse-ExtensibleAPI: true
|
12 |
+
Export-Package: org.eclipse.jgit.annotations;version="7.0.0",
|
13 |
+
org.eclipse.jgit.api;version="7.0.0";
|
14 |
uses:="org.eclipse.jgit.transport,
|
15 |
org.eclipse.jgit.notes,
|
16 |
org.eclipse.jgit.dircache,
|
|
|
25 |
org.eclipse.jgit.revwalk.filter,
|
26 |
org.eclipse.jgit.blame,
|
27 |
org.eclipse.jgit.merge",
|
28 |
+
org.eclipse.jgit.api.errors;version="7.0.0";
|
29 |
uses:="org.eclipse.jgit.lib,
|
30 |
org.eclipse.jgit.errors",
|
31 |
+
org.eclipse.jgit.attributes;version="7.0.0";
|
32 |
uses:="org.eclipse.jgit.lib,
|
33 |
org.eclipse.jgit.treewalk",
|
34 |
+
org.eclipse.jgit.blame;version="7.0.0";
|
35 |
uses:="org.eclipse.jgit.lib,
|
36 |
org.eclipse.jgit.revwalk,
|
37 |
org.eclipse.jgit.treewalk.filter,
|
38 |
org.eclipse.jgit.diff",
|
39 |
+
org.eclipse.jgit.diff;version="7.0.0";
|
40 |
uses:="org.eclipse.jgit.lib,
|
41 |
org.eclipse.jgit.attributes,
|
42 |
org.eclipse.jgit.revwalk,
|
|
|
44 |
org.eclipse.jgit.treewalk.filter,
|
45 |
org.eclipse.jgit.treewalk,
|
46 |
org.eclipse.jgit.util",
|
47 |
+
org.eclipse.jgit.dircache;version="7.0.0";
|
48 |
uses:="org.eclipse.jgit.events,
|
49 |
org.eclipse.jgit.lib,
|
50 |
org.eclipse.jgit.attributes,
|
51 |
org.eclipse.jgit.treewalk,
|
52 |
org.eclipse.jgit.util",
|
53 |
+
org.eclipse.jgit.errors;version="7.0.0";
|
54 |
uses:="org.eclipse.jgit.transport,
|
55 |
org.eclipse.jgit.dircache,
|
56 |
org.eclipse.jgit.lib,
|
57 |
org.eclipse.jgit.internal.storage.pack",
|
58 |
+
org.eclipse.jgit.events;version="7.0.0";
|
59 |
uses:="org.eclipse.jgit.lib",
|
60 |
+
org.eclipse.jgit.fnmatch;version="7.0.0",
|
61 |
+
org.eclipse.jgit.gitrepo;version="7.0.0";
|
62 |
uses:="org.xml.sax.helpers,
|
63 |
org.eclipse.jgit.api,
|
64 |
org.eclipse.jgit.lib,
|
65 |
org.eclipse.jgit.revwalk,
|
66 |
org.xml.sax",
|
67 |
+
org.eclipse.jgit.gitrepo.internal;version="7.0.0";x-internal:=true,
|
68 |
+
org.eclipse.jgit.hooks;version="7.0.0";uses:="org.eclipse.jgit.lib",
|
69 |
+
org.eclipse.jgit.ignore;version="7.0.0",
|
70 |
+
org.eclipse.jgit.ignore.internal;version="7.0.0";
|
71 |
x-friends:="org.eclipse.jgit.test",
|
72 |
+
org.eclipse.jgit.internal;version="7.0.0";
|
73 |
x-friends:="org.eclipse.jgit.test,
|
74 |
org.eclipse.jgit.http.test",
|
75 |
+
org.eclipse.jgit.internal.diff;version="7.0.0";
|
76 |
x-friends:="org.eclipse.jgit.test",
|
77 |
+
org.eclipse.jgit.internal.diffmergetool;version="7.0.0";
|
78 |
x-friends:="org.eclipse.jgit.test,
|
79 |
org.eclipse.jgit.pgm.test,
|
80 |
org.eclipse.jgit.pgm,
|
81 |
org.eclipse.egit.ui",
|
82 |
+
org.eclipse.jgit.internal.fsck;version="7.0.0";
|
83 |
x-friends:="org.eclipse.jgit.test",
|
84 |
+
org.eclipse.jgit.internal.revwalk;version="7.0.0";
|
85 |
x-friends:="org.eclipse.jgit.test",
|
86 |
+
org.eclipse.jgit.internal.storage.commitgraph;version="7.0.0";
|
87 |
x-friends:="org.eclipse.jgit.test",
|
88 |
+
org.eclipse.jgit.internal.storage.dfs;version="7.0.0";
|
89 |
x-friends:="org.eclipse.jgit.test,
|
90 |
org.eclipse.jgit.http.server,
|
91 |
org.eclipse.jgit.http.test,
|
92 |
org.eclipse.jgit.lfs.test",
|
93 |
+
org.eclipse.jgit.internal.storage.file;version="7.0.0";
|
94 |
x-friends:="org.eclipse.jgit.test,
|
95 |
org.eclipse.jgit.junit,
|
96 |
org.eclipse.jgit.junit.http,
|
|
|
99 |
org.eclipse.jgit.pgm,
|
100 |
org.eclipse.jgit.pgm.test,
|
101 |
org.eclipse.jgit.ssh.apache",
|
102 |
+
org.eclipse.jgit.internal.storage.io;version="7.0.0";
|
103 |
x-friends:="org.eclipse.jgit.junit,
|
104 |
org.eclipse.jgit.test,
|
105 |
org.eclipse.jgit.pgm",
|
106 |
+
org.eclipse.jgit.internal.storage.memory;version="7.0.0";
|
107 |
x-friends:="org.eclipse.jgit.test",
|
108 |
+
org.eclipse.jgit.internal.storage.pack;version="7.0.0";
|
109 |
x-friends:="org.eclipse.jgit.junit,
|
110 |
org.eclipse.jgit.test,
|
111 |
org.eclipse.jgit.pgm",
|
112 |
+
org.eclipse.jgit.internal.storage.reftable;version="7.0.0";
|
113 |
x-friends:="org.eclipse.jgit.http.test,
|
114 |
org.eclipse.jgit.junit,
|
115 |
org.eclipse.jgit.test,
|
116 |
org.eclipse.jgit.pgm",
|
117 |
+
org.eclipse.jgit.internal.submodule;version="7.0.0";x-internal:=true,
|
118 |
+
org.eclipse.jgit.internal.transport.connectivity;version="7.0.0";
|
119 |
x-friends:="org.eclipse.jgit.test",
|
120 |
+
org.eclipse.jgit.internal.transport.http;version="7.0.0";
|
121 |
x-friends:="org.eclipse.jgit.test",
|
122 |
+
org.eclipse.jgit.internal.transport.parser;version="7.0.0";
|
123 |
x-friends:="org.eclipse.jgit.http.server,
|
124 |
org.eclipse.jgit.test",
|
125 |
+
org.eclipse.jgit.internal.transport.ssh;version="7.0.0";
|
126 |
x-friends:="org.eclipse.jgit.ssh.apache,
|
127 |
org.eclipse.jgit.ssh.jsch,
|
128 |
org.eclipse.jgit.test",
|
129 |
+
org.eclipse.jgit.internal.util;version="7.0.0";
|
130 |
x-friends:=" org.eclipse.jgit.junit",
|
131 |
+
org.eclipse.jgit.lib;version="7.0.0";
|
132 |
uses:="org.eclipse.jgit.transport,
|
133 |
org.eclipse.jgit.util.sha1,
|
134 |
org.eclipse.jgit.dircache,
|
|
|
142 |
org.eclipse.jgit.util,
|
143 |
org.eclipse.jgit.submodule,
|
144 |
org.eclipse.jgit.util.time",
|
145 |
+
org.eclipse.jgit.lib.internal;version="7.0.0";
|
146 |
x-friends:="org.eclipse.jgit.test,
|
147 |
org.eclipse.jgit.pgm,
|
148 |
org.eclipse.egit.ui",
|
149 |
+
org.eclipse.jgit.logging;version="7.0.0",
|
150 |
+
org.eclipse.jgit.merge;version="7.0.0";
|
151 |
uses:="org.eclipse.jgit.dircache,
|
152 |
org.eclipse.jgit.lib,
|
153 |
org.eclipse.jgit.revwalk,
|
|
|
156 |
org.eclipse.jgit.util,
|
157 |
org.eclipse.jgit.api,
|
158 |
org.eclipse.jgit.attributes",
|
159 |
+
org.eclipse.jgit.nls;version="7.0.0",
|
160 |
+
org.eclipse.jgit.notes;version="7.0.0";
|
161 |
uses:="org.eclipse.jgit.lib,
|
162 |
org.eclipse.jgit.revwalk,
|
163 |
org.eclipse.jgit.treewalk,
|
164 |
org.eclipse.jgit.merge",
|
165 |
+
org.eclipse.jgit.patch;version="7.0.0";
|
166 |
uses:="org.eclipse.jgit.lib,
|
167 |
org.eclipse.jgit.diff",
|
168 |
+
org.eclipse.jgit.revplot;version="7.0.0";
|
169 |
uses:="org.eclipse.jgit.lib,
|
170 |
org.eclipse.jgit.revwalk",
|
171 |
+
org.eclipse.jgit.revwalk;version="7.0.0";
|
172 |
uses:="org.eclipse.jgit.lib,
|
173 |
org.eclipse.jgit.diff,
|
174 |
org.eclipse.jgit.treewalk.filter,
|
175 |
org.eclipse.jgit.revwalk.filter,
|
176 |
org.eclipse.jgit.treewalk",
|
177 |
+
org.eclipse.jgit.revwalk.filter;version="7.0.0";
|
178 |
uses:="org.eclipse.jgit.revwalk,
|
179 |
org.eclipse.jgit.lib,
|
180 |
org.eclipse.jgit.util",
|
181 |
+
org.eclipse.jgit.storage.file;version="7.0.0";
|
182 |
uses:="org.eclipse.jgit.lib,
|
183 |
org.eclipse.jgit.util",
|
184 |
+
org.eclipse.jgit.storage.pack;version="7.0.0";
|
185 |
uses:="org.eclipse.jgit.lib",
|
186 |
+
org.eclipse.jgit.submodule;version="7.0.0";
|
187 |
uses:="org.eclipse.jgit.lib,
|
188 |
org.eclipse.jgit.diff,
|
189 |
org.eclipse.jgit.treewalk.filter,
|
190 |
org.eclipse.jgit.treewalk,
|
191 |
org.eclipse.jgit.util",
|
192 |
+
org.eclipse.jgit.transport;version="7.0.0";
|
193 |
uses:="javax.crypto,
|
194 |
org.eclipse.jgit.util.io,
|
195 |
org.eclipse.jgit.lib,
|
|
|
202 |
org.eclipse.jgit.transport.resolver,
|
203 |
org.eclipse.jgit.storage.pack,
|
204 |
org.eclipse.jgit.errors",
|
205 |
+
org.eclipse.jgit.transport.http;version="7.0.0";
|
206 |
uses:="javax.net.ssl",
|
207 |
+
org.eclipse.jgit.transport.resolver;version="7.0.0";
|
208 |
uses:="org.eclipse.jgit.transport,
|
209 |
org.eclipse.jgit.lib",
|
210 |
+
org.eclipse.jgit.treewalk;version="7.0.0";
|
211 |
uses:="org.eclipse.jgit.dircache,
|
212 |
org.eclipse.jgit.lib,
|
213 |
org.eclipse.jgit.attributes,
|
214 |
org.eclipse.jgit.revwalk,
|
215 |
org.eclipse.jgit.treewalk.filter,
|
216 |
org.eclipse.jgit.util",
|
217 |
+
org.eclipse.jgit.treewalk.filter;version="7.0.0";
|
218 |
uses:="org.eclipse.jgit.treewalk",
|
219 |
+
org.eclipse.jgit.util;version="7.0.0";
|
220 |
uses:="org.eclipse.jgit.transport,
|
221 |
org.eclipse.jgit.hooks,
|
222 |
org.eclipse.jgit.revwalk,
|
|
|
229 |
org.eclipse.jgit.treewalk,
|
230 |
javax.net.ssl,
|
231 |
org.eclipse.jgit.util.time",
|
232 |
+
org.eclipse.jgit.util.io;version="7.0.0";
|
233 |
uses:="org.eclipse.jgit.attributes,
|
234 |
org.eclipse.jgit.lib,
|
235 |
org.eclipse.jgit.treewalk",
|
236 |
+
org.eclipse.jgit.util.sha1;version="7.0.0",
|
237 |
+
org.eclipse.jgit.util.time;version="7.0.0"
|
238 |
+
Bundle-RequiredExecutionEnvironment: JavaSE-17
|
239 |
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
|
240 |
javax.crypto,
|
241 |
javax.management,
|
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
|
|
3 |
Bundle-Name: org.eclipse.jgit - Sources
|
4 |
Bundle-SymbolicName: org.eclipse.jgit.source
|
5 |
Bundle-Vendor: Eclipse.org - JGit
|
6 |
-
Bundle-Version:
|
7 |
-
Eclipse-SourceBundle: org.eclipse.jgit;version="
|
|
|
3 |
Bundle-Name: org.eclipse.jgit - Sources
|
4 |
Bundle-SymbolicName: org.eclipse.jgit.source
|
5 |
Bundle-Vendor: Eclipse.org - JGit
|
6 |
+
Bundle-Version: 7.0.0.202409031743-r
|
7 |
+
Eclipse-SourceBundle: org.eclipse.jgit;version="7.0.0.202409031743-r";roots="."
|
@@ -20,7 +20,7 @@
|
|
20 |
<parent>
|
21 |
<groupId>org.eclipse.jgit</groupId>
|
22 |
<artifactId>org.eclipse.jgit-parent</artifactId>
|
23 |
-
<version>
|
24 |
</parent>
|
25 |
|
26 |
<artifactId>org.eclipse.jgit</artifactId>
|
|
|
20 |
<parent>
|
21 |
<groupId>org.eclipse.jgit</groupId>
|
22 |
<artifactId>org.eclipse.jgit-parent</artifactId>
|
23 |
+
<version>7.0.0.202409031743-r</version>
|
24 |
</parent>
|
25 |
|
26 |
<artifactId>org.eclipse.jgit</artifactId>
|
@@ -285,6 +285,9 @@ DIRCUnrecognizedExtendedFlags=Unrecognized extended flags: {0}
|
|
285 |
downloadCancelled=Download cancelled
|
286 |
downloadCancelledDuringIndexing=Download cancelled during indexing
|
287 |
duplicateAdvertisementsOf=duplicate advertisements of {0}
|
|
|
|
|
|
|
288 |
duplicateRef=Duplicate ref: {0}
|
289 |
duplicateRefAttribute=Duplicate ref attribute: {0}
|
290 |
duplicateRemoteRefUpdateIsIllegal=Duplicate remote ref update is illegal. Affected remote name: {0}
|
@@ -539,6 +542,8 @@ noMergeBase=No merge base could be determined. Reason={0}. {1}
|
|
539 |
noMergeHeadSpecified=No merge head specified
|
540 |
nonBareLinkFilesNotSupported=Link files are not supported with nonbare repos
|
541 |
nonCommitToHeads=Cannot point a branch to a non-commit object
|
|
|
|
|
542 |
noPathAttributesFound=No Attributes found for {0}.
|
543 |
noSuchRef=no such ref
|
544 |
noSuchRefKnown=no such ref: {0}
|
@@ -571,7 +576,6 @@ obtainingCommitsForCherryPick=Obtaining commits that need to be cherry-picked
|
|
571 |
oldIdMustNotBeNull=Expected old ID must not be null
|
572 |
onlyOneFetchSupported=Only one fetch supported
|
573 |
onlyOneOperationCallPerConnectionIsSupported=Only one operation call per connection is supported.
|
574 |
-
onlyOpenPgpSupportedForSigning=OpenPGP is the only supported signing option with JGit at this time (gpg.format must be set to openpgp).
|
575 |
openFilesMustBeAtLeast1=Open files must be >= 1
|
576 |
openingConnection=Opening connection
|
577 |
operationCanceled=Operation {0} was canceled
|
@@ -718,6 +722,8 @@ shortSkipOfBlock=Short skip of block.
|
|
718 |
shutdownCleanup=Cleanup {} during JVM shutdown
|
719 |
shutdownCleanupFailed=Cleanup during JVM shutdown failed
|
720 |
shutdownCleanupListenerFailed=Cleanup of {0} during JVM shutdown failed
|
|
|
|
|
721 |
signatureVerificationError=Signature verification failed
|
722 |
signatureVerificationUnavailable=No signature verifier registered
|
723 |
signedTagMessageNoLf=A non-empty message of a signed tag must end in LF.
|
@@ -803,6 +809,7 @@ truncatedHunkOldLinesMissing=Truncated hunk, at least {0} old lines is missing
|
|
803 |
tSizeMustBeGreaterOrEqual1=tSize must be >= 1
|
804 |
unableToCheckConnectivity=Unable to check connectivity.
|
805 |
unableToCreateNewObject=Unable to create new object: {0}
|
|
|
806 |
unableToReadFullInt=Unable to read a full int from the stream
|
807 |
unableToReadPackfile=Unable to read packfile {0}
|
808 |
unableToRemovePath=Unable to remove path ''{0}''
|
@@ -829,6 +836,7 @@ unknownObject=unknown object
|
|
829 |
unknownObjectInIndex=unknown object {0} found in index but not in pack file
|
830 |
unknownObjectType=Unknown object type {0}.
|
831 |
unknownObjectType2=unknown
|
|
|
832 |
unknownPositionEncoding=Unknown position encoding %s
|
833 |
unknownRefStorageFormat=Unknown ref storage format "{0}"
|
834 |
unknownRepositoryFormat=Unknown repository format
|
|
|
285 |
downloadCancelled=Download cancelled
|
286 |
downloadCancelledDuringIndexing=Download cancelled during indexing
|
287 |
duplicateAdvertisementsOf=duplicate advertisements of {0}
|
288 |
+
duplicateCacheTablesGiven=Duplicate cache tables given
|
289 |
+
duplicatePackExtensionsForCacheTables=Duplicate pack extension {0} in cache tables
|
290 |
+
duplicatePackExtensionsSet=Attempting to configure duplicate pack extensions: {0}.{1}.{2} contains {3}
|
291 |
duplicateRef=Duplicate ref: {0}
|
292 |
duplicateRefAttribute=Duplicate ref attribute: {0}
|
293 |
duplicateRemoteRefUpdateIsIllegal=Duplicate remote ref update is illegal. Affected remote name: {0}
|
|
|
542 |
noMergeHeadSpecified=No merge head specified
|
543 |
nonBareLinkFilesNotSupported=Link files are not supported with nonbare repos
|
544 |
nonCommitToHeads=Cannot point a branch to a non-commit object
|
545 |
+
noPackExtConfigurationGiven=No PackExt configuration given
|
546 |
+
noPackExtGivenForConfiguration=No PackExt given for configuration
|
547 |
noPathAttributesFound=No Attributes found for {0}.
|
548 |
noSuchRef=no such ref
|
549 |
noSuchRefKnown=no such ref: {0}
|
|
|
576 |
oldIdMustNotBeNull=Expected old ID must not be null
|
577 |
onlyOneFetchSupported=Only one fetch supported
|
578 |
onlyOneOperationCallPerConnectionIsSupported=Only one operation call per connection is supported.
|
|
|
579 |
openFilesMustBeAtLeast1=Open files must be >= 1
|
580 |
openingConnection=Opening connection
|
581 |
operationCanceled=Operation {0} was canceled
|
|
|
722 |
shutdownCleanup=Cleanup {} during JVM shutdown
|
723 |
shutdownCleanupFailed=Cleanup during JVM shutdown failed
|
724 |
shutdownCleanupListenerFailed=Cleanup of {0} during JVM shutdown failed
|
725 |
+
signatureServiceConflict={0} conflict for type {1}. Already registered is {2}; additional factory {3} is ignored.
|
726 |
+
signatureTypeUnknown=No signer for {0} signatures. Use another signature type for git config gpg.format, or do not sign.
|
727 |
signatureVerificationError=Signature verification failed
|
728 |
signatureVerificationUnavailable=No signature verifier registered
|
729 |
signedTagMessageNoLf=A non-empty message of a signed tag must end in LF.
|
|
|
809 |
tSizeMustBeGreaterOrEqual1=tSize must be >= 1
|
810 |
unableToCheckConnectivity=Unable to check connectivity.
|
811 |
unableToCreateNewObject=Unable to create new object: {0}
|
812 |
+
unableToReadFullArray=Unable to read an array with {0} elements from the stream
|
813 |
unableToReadFullInt=Unable to read a full int from the stream
|
814 |
unableToReadPackfile=Unable to read packfile {0}
|
815 |
unableToRemovePath=Unable to remove path ''{0}''
|
|
|
836 |
unknownObjectInIndex=unknown object {0} found in index but not in pack file
|
837 |
unknownObjectType=Unknown object type {0}.
|
838 |
unknownObjectType2=unknown
|
839 |
+
unknownPackExtension=Unknown pack extension: {0}.{1}.{2}={3}
|
840 |
unknownPositionEncoding=Unknown position encoding %s
|
841 |
unknownRefStorageFormat=Unknown ref storage format "{0}"
|
842 |
unknownRepositoryFormat=Unknown repository format
|
@@ -641,24 +641,6 @@ public CheckoutCommand setOrphan(boolean orphan) {
|
|
641 |
return this;
|
642 |
}
|
643 |
|
644 |
-
/**
|
645 |
-
* Specify to force the ref update in case of a branch switch.
|
646 |
-
*
|
647 |
-
* @param force
|
648 |
-
* if <code>true</code> and the branch with the given name
|
649 |
-
* already exists, the start-point of an existing branch will be
|
650 |
-
* set to a new start-point; if false, the existing branch will
|
651 |
-
* not be changed
|
652 |
-
* @return this instance
|
653 |
-
* @deprecated this method was badly named comparing its semantics to native
|
654 |
-
* git's checkout --force option, use
|
655 |
-
* {@link #setForceRefUpdate(boolean)} instead
|
656 |
-
*/
|
657 |
-
@Deprecated
|
658 |
-
public CheckoutCommand setForce(boolean force) {
|
659 |
-
return setForceRefUpdate(force);
|
660 |
-
}
|
661 |
-
|
662 |
/**
|
663 |
* Specify to force the ref update in case of a branch switch.
|
664 |
*
|
|
|
641 |
return this;
|
642 |
}
|
643 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
644 |
/**
|
645 |
* Specify to force the ref update in case of a branch switch.
|
646 |
*
|
@@ -51,9 +51,6 @@
|
|
51 |
import org.eclipse.jgit.lib.Constants;
|
52 |
import org.eclipse.jgit.lib.FileMode;
|
53 |
import org.eclipse.jgit.lib.GpgConfig;
|
54 |
-
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
|
55 |
-
import org.eclipse.jgit.lib.GpgObjectSigner;
|
56 |
-
import org.eclipse.jgit.lib.GpgSigner;
|
57 |
import org.eclipse.jgit.lib.ObjectId;
|
58 |
import org.eclipse.jgit.lib.ObjectInserter;
|
59 |
import org.eclipse.jgit.lib.PersonIdent;
|
@@ -62,6 +59,8 @@
|
|
62 |
import org.eclipse.jgit.lib.RefUpdate.Result;
|
63 |
import org.eclipse.jgit.lib.Repository;
|
64 |
import org.eclipse.jgit.lib.RepositoryState;
|
|
|
|
|
65 |
import org.eclipse.jgit.revwalk.RevCommit;
|
66 |
import org.eclipse.jgit.revwalk.RevObject;
|
67 |
import org.eclipse.jgit.revwalk.RevTag;
|
@@ -129,7 +128,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
|
|
129 |
|
130 |
private String signingKey;
|
131 |
|
132 |
-
private
|
133 |
|
134 |
private GpgConfig gpgConfig;
|
135 |
|
@@ -319,30 +318,22 @@ private void checkIfEmpty(RevWalk rw, ObjectId headId, ObjectId indexTreeId)
|
|
319 |
}
|
320 |
}
|
321 |
|
322 |
-
private void sign(CommitBuilder commit)
|
323 |
-
CanceledException,
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
|
|
|
|
329 |
}
|
330 |
}
|
331 |
if (signingKey == null) {
|
332 |
signingKey = gpgConfig.getSigningKey();
|
333 |
}
|
334 |
-
|
335 |
-
|
336 |
-
signingKey, committer, credentialsProvider,
|
337 |
-
gpgConfig);
|
338 |
-
} else {
|
339 |
-
if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
|
340 |
-
throw new UnsupportedSigningFormatException(JGitText
|
341 |
-
.get().onlyOpenPgpSupportedForSigning);
|
342 |
-
}
|
343 |
-
gpgSigner.sign(commit, signingKey, committer,
|
344 |
-
credentialsProvider);
|
345 |
-
}
|
346 |
}
|
347 |
|
348 |
private void updateRef(RepositoryState state, ObjectId headId,
|
@@ -1097,22 +1088,22 @@ public CommitCommand setSign(Boolean sign) {
|
|
1097 |
}
|
1098 |
|
1099 |
/**
|
1100 |
-
* Sets the {@link
|
1101 |
*
|
1102 |
* @param signer
|
1103 |
* to use; if {@code null}, the default signer will be used
|
1104 |
* @return {@code this}
|
1105 |
-
* @since
|
1106 |
*/
|
1107 |
-
public CommitCommand
|
1108 |
checkCallable();
|
1109 |
-
this.
|
1110 |
return this;
|
1111 |
}
|
1112 |
|
1113 |
/**
|
1114 |
* Sets an external {@link GpgConfig} to use. Whether it will be used is at
|
1115 |
-
* the discretion of the {@link #
|
1116 |
*
|
1117 |
* @param config
|
1118 |
* to set; if {@code null}, the config will be loaded from the
|
|
|
51 |
import org.eclipse.jgit.lib.Constants;
|
52 |
import org.eclipse.jgit.lib.FileMode;
|
53 |
import org.eclipse.jgit.lib.GpgConfig;
|
|
|
|
|
|
|
54 |
import org.eclipse.jgit.lib.ObjectId;
|
55 |
import org.eclipse.jgit.lib.ObjectInserter;
|
56 |
import org.eclipse.jgit.lib.PersonIdent;
|
|
|
59 |
import org.eclipse.jgit.lib.RefUpdate.Result;
|
60 |
import org.eclipse.jgit.lib.Repository;
|
61 |
import org.eclipse.jgit.lib.RepositoryState;
|
62 |
+
import org.eclipse.jgit.lib.Signer;
|
63 |
+
import org.eclipse.jgit.lib.Signers;
|
64 |
import org.eclipse.jgit.revwalk.RevCommit;
|
65 |
import org.eclipse.jgit.revwalk.RevObject;
|
66 |
import org.eclipse.jgit.revwalk.RevTag;
|
|
|
128 |
|
129 |
private String signingKey;
|
130 |
|
131 |
+
private Signer signer;
|
132 |
|
133 |
private GpgConfig gpgConfig;
|
134 |
|
|
|
318 |
}
|
319 |
}
|
320 |
|
321 |
+
private void sign(CommitBuilder commit)
|
322 |
+
throws CanceledException, IOException,
|
323 |
+
UnsupportedSigningFormatException {
|
324 |
+
if (signer == null) {
|
325 |
+
signer = Signers.get(gpgConfig.getKeyFormat());
|
326 |
+
if (signer == null) {
|
327 |
+
throw new UnsupportedSigningFormatException(MessageFormat
|
328 |
+
.format(JGitText.get().signatureTypeUnknown,
|
329 |
+
gpgConfig.getKeyFormat().toConfigValue()));
|
330 |
}
|
331 |
}
|
332 |
if (signingKey == null) {
|
333 |
signingKey = gpgConfig.getSigningKey();
|
334 |
}
|
335 |
+
signer.signObject(repo, gpgConfig, commit, committer, signingKey,
|
336 |
+
credentialsProvider);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
}
|
338 |
|
339 |
private void updateRef(RepositoryState state, ObjectId headId,
|
|
|
1088 |
}
|
1089 |
|
1090 |
/**
|
1091 |
+
* Sets the {@link Signer} to use if the commit is to be signed.
|
1092 |
*
|
1093 |
* @param signer
|
1094 |
* to use; if {@code null}, the default signer will be used
|
1095 |
* @return {@code this}
|
1096 |
+
* @since 7.0
|
1097 |
*/
|
1098 |
+
public CommitCommand setSigner(Signer signer) {
|
1099 |
checkCallable();
|
1100 |
+
this.signer = signer;
|
1101 |
return this;
|
1102 |
}
|
1103 |
|
1104 |
/**
|
1105 |
* Sets an external {@link GpgConfig} to use. Whether it will be used is at
|
1106 |
+
* the discretion of the {@link #setSigner(Signer)}.
|
1107 |
*
|
1108 |
* @param config
|
1109 |
* to set; if {@code null}, the config will be loaded from the
|
@@ -46,18 +46,6 @@ protected RemoteRemoveCommand(Repository repo) {
|
|
46 |
super(repo);
|
47 |
}
|
48 |
|
49 |
-
/**
|
50 |
-
* The name of the remote to remove.
|
51 |
-
*
|
52 |
-
* @param name
|
53 |
-
* a remote name
|
54 |
-
* @deprecated use {@link #setRemoteName} instead
|
55 |
-
*/
|
56 |
-
@Deprecated
|
57 |
-
public void setName(String name) {
|
58 |
-
this.remoteName = name;
|
59 |
-
}
|
60 |
-
|
61 |
/**
|
62 |
* The name of the remote to remove.
|
63 |
*
|
|
|
46 |
super(repo);
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
/**
|
50 |
* The name of the remote to remove.
|
51 |
*
|
@@ -68,18 +68,6 @@ protected RemoteSetUrlCommand(Repository repo) {
|
|
68 |
super(repo);
|
69 |
}
|
70 |
|
71 |
-
/**
|
72 |
-
* The name of the remote to change the URL for.
|
73 |
-
*
|
74 |
-
* @param name
|
75 |
-
* a remote name
|
76 |
-
* @deprecated use {@link #setRemoteName} instead
|
77 |
-
*/
|
78 |
-
@Deprecated
|
79 |
-
public void setName(String name) {
|
80 |
-
this.remoteName = name;
|
81 |
-
}
|
82 |
-
|
83 |
/**
|
84 |
* The name of the remote to change the URL for.
|
85 |
*
|
@@ -93,18 +81,6 @@ public RemoteSetUrlCommand setRemoteName(String remoteName) {
|
|
93 |
return this;
|
94 |
}
|
95 |
|
96 |
-
/**
|
97 |
-
* The new URL for the remote.
|
98 |
-
*
|
99 |
-
* @param uri
|
100 |
-
* an URL for the remote
|
101 |
-
* @deprecated use {@link #setRemoteUri} instead
|
102 |
-
*/
|
103 |
-
@Deprecated
|
104 |
-
public void setUri(URIish uri) {
|
105 |
-
this.remoteUri = uri;
|
106 |
-
}
|
107 |
-
|
108 |
/**
|
109 |
* The new URL for the remote.
|
110 |
*
|
@@ -118,23 +94,6 @@ public RemoteSetUrlCommand setRemoteUri(URIish remoteUri) {
|
|
118 |
return this;
|
119 |
}
|
120 |
|
121 |
-
/**
|
122 |
-
* Whether to change the push URL of the remote instead of the fetch URL.
|
123 |
-
*
|
124 |
-
* @param push
|
125 |
-
* <code>true</code> to set the push url, <code>false</code> to
|
126 |
-
* set the fetch url
|
127 |
-
* @deprecated use {@link #setUriType} instead
|
128 |
-
*/
|
129 |
-
@Deprecated
|
130 |
-
public void setPush(boolean push) {
|
131 |
-
if (push) {
|
132 |
-
setUriType(UriType.PUSH);
|
133 |
-
} else {
|
134 |
-
setUriType(UriType.FETCH);
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
/**
|
139 |
* Whether to change the push URL of the remote instead of the fetch URL.
|
140 |
*
|
|
|
68 |
super(repo);
|
69 |
}
|
70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
/**
|
72 |
* The name of the remote to change the URL for.
|
73 |
*
|
|
|
81 |
return this;
|
82 |
}
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
/**
|
85 |
* The new URL for the remote.
|
86 |
*
|
|
|
94 |
return this;
|
95 |
}
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
/**
|
98 |
* Whether to change the push URL of the remote instead of the fetch URL.
|
99 |
*
|
@@ -260,18 +260,6 @@ public ObjectId call() throws GitAPIException,
|
|
260 |
}
|
261 |
}
|
262 |
|
263 |
-
/**
|
264 |
-
* Whether to restore the index state
|
265 |
-
*
|
266 |
-
* @param applyIndex
|
267 |
-
* true (default) if the command should restore the index state
|
268 |
-
* @deprecated use {@link #setRestoreIndex} instead
|
269 |
-
*/
|
270 |
-
@Deprecated
|
271 |
-
public void setApplyIndex(boolean applyIndex) {
|
272 |
-
this.restoreIndex = applyIndex;
|
273 |
-
}
|
274 |
-
|
275 |
/**
|
276 |
* Whether to restore the index state
|
277 |
*
|
@@ -316,19 +304,6 @@ public StashApplyCommand setContentMergeStrategy(
|
|
316 |
return this;
|
317 |
}
|
318 |
|
319 |
-
/**
|
320 |
-
* Whether the command should restore untracked files
|
321 |
-
*
|
322 |
-
* @param applyUntracked
|
323 |
-
* true (default) if the command should restore untracked files
|
324 |
-
* @since 3.4
|
325 |
-
* @deprecated use {@link #setRestoreUntracked} instead
|
326 |
-
*/
|
327 |
-
@Deprecated
|
328 |
-
public void setApplyUntracked(boolean applyUntracked) {
|
329 |
-
this.restoreUntracked = applyUntracked;
|
330 |
-
}
|
331 |
-
|
332 |
/**
|
333 |
* Whether the command should restore untracked files
|
334 |
*
|
|
|
260 |
}
|
261 |
}
|
262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
/**
|
264 |
* Whether to restore the index state
|
265 |
*
|
|
|
304 |
return this;
|
305 |
}
|
306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
/**
|
308 |
* Whether the command should restore untracked files
|
309 |
*
|
@@ -176,7 +176,7 @@ public Repository call() throws GitAPIException {
|
|
176 |
CloneCommand clone = Git.cloneRepository();
|
177 |
configure(clone);
|
178 |
clone.setDirectory(moduleDirectory);
|
179 |
-
clone.setGitDir(new File(new File(repo.
|
180 |
Constants.MODULES), path));
|
181 |
clone.setURI(resolvedUri);
|
182 |
if (monitor != null)
|
|
|
176 |
CloneCommand clone = Git.cloneRepository();
|
177 |
configure(clone);
|
178 |
clone.setDirectory(moduleDirectory);
|
179 |
+
clone.setGitDir(new File(new File(repo.getCommonDirectory(),
|
180 |
Constants.MODULES), path));
|
181 |
clone.setURI(resolvedUri);
|
182 |
if (monitor != null)
|
@@ -128,7 +128,7 @@ private Repository getOrCloneSubmodule(SubmoduleWalk generator, String url)
|
|
128 |
clone.setURI(url);
|
129 |
clone.setDirectory(generator.getDirectory());
|
130 |
clone.setGitDir(
|
131 |
-
new File(new File(repo.
|
132 |
generator.getPath()));
|
133 |
if (monitor != null) {
|
134 |
clone.setProgressMonitor(monitor);
|
|
|
128 |
clone.setURI(url);
|
129 |
clone.setDirectory(generator.getDirectory());
|
130 |
clone.setGitDir(
|
131 |
+
new File(new File(repo.getCommonDirectory(), Constants.MODULES),
|
132 |
generator.getPath()));
|
133 |
if (monitor != null) {
|
134 |
clone.setProgressMonitor(monitor);
|
@@ -18,14 +18,11 @@
|
|
18 |
import org.eclipse.jgit.api.errors.JGitInternalException;
|
19 |
import org.eclipse.jgit.api.errors.NoHeadException;
|
20 |
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
|
21 |
-
import org.eclipse.jgit.api.errors.ServiceUnavailableException;
|
22 |
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
|
23 |
import org.eclipse.jgit.internal.JGitText;
|
24 |
import org.eclipse.jgit.lib.Constants;
|
25 |
import org.eclipse.jgit.lib.GpgConfig;
|
26 |
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
|
27 |
-
import org.eclipse.jgit.lib.GpgObjectSigner;
|
28 |
-
import org.eclipse.jgit.lib.GpgSigner;
|
29 |
import org.eclipse.jgit.lib.ObjectId;
|
30 |
import org.eclipse.jgit.lib.ObjectInserter;
|
31 |
import org.eclipse.jgit.lib.PersonIdent;
|
@@ -33,6 +30,8 @@
|
|
33 |
import org.eclipse.jgit.lib.RefUpdate;
|
34 |
import org.eclipse.jgit.lib.RefUpdate.Result;
|
35 |
import org.eclipse.jgit.lib.Repository;
|
|
|
|
|
36 |
import org.eclipse.jgit.lib.TagBuilder;
|
37 |
import org.eclipse.jgit.revwalk.RevObject;
|
38 |
import org.eclipse.jgit.revwalk.RevWalk;
|
@@ -79,7 +78,7 @@ public class TagCommand extends GitCommand<Ref> {
|
|
79 |
|
80 |
private GpgConfig gpgConfig;
|
81 |
|
82 |
-
private
|
83 |
|
84 |
private CredentialsProvider credentialsProvider;
|
85 |
|
@@ -133,9 +132,9 @@ public Ref call() throws GitAPIException, ConcurrentRefUpdateException,
|
|
133 |
newTag.setTagger(tagger);
|
134 |
newTag.setObjectId(id);
|
135 |
|
136 |
-
if (
|
137 |
-
|
138 |
-
credentialsProvider
|
139 |
}
|
140 |
|
141 |
// write the tag object
|
@@ -196,15 +195,12 @@ private Ref updateTagRef(ObjectId tagId, RevWalk revWalk,
|
|
196 |
*
|
197 |
* @throws InvalidTagNameException
|
198 |
* if the tag name is null or invalid
|
199 |
-
* @throws ServiceUnavailableException
|
200 |
-
* if the tag should be signed but no signer can be found
|
201 |
* @throws UnsupportedSigningFormatException
|
202 |
* if the tag should be signed but {@code gpg.format} is not
|
203 |
* {@link GpgFormat#OPENPGP}
|
204 |
*/
|
205 |
private void processOptions()
|
206 |
-
throws InvalidTagNameException,
|
207 |
-
UnsupportedSigningFormatException {
|
208 |
if (name == null
|
209 |
|| !Repository.isValidRefName(Constants.R_TAGS + name)) {
|
210 |
throw new InvalidTagNameException(
|
@@ -230,16 +226,15 @@ private void processOptions()
|
|
230 |
doSign = gpgConfig.isSignAnnotated();
|
231 |
}
|
232 |
if (doSign) {
|
233 |
-
if (
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
}
|
242 |
-
gpgSigner = (GpgObjectSigner) signer;
|
243 |
}
|
244 |
// The message of a signed tag must end in a newline because
|
245 |
// the signature will be appended.
|
@@ -326,22 +321,22 @@ public TagCommand setSigned(boolean signed) {
|
|
326 |
}
|
327 |
|
328 |
/**
|
329 |
-
* Sets the {@link
|
330 |
*
|
331 |
* @param signer
|
332 |
* to use; if {@code null}, the default signer will be used
|
333 |
* @return {@code this}
|
334 |
-
* @since
|
335 |
*/
|
336 |
-
public TagCommand
|
337 |
checkCallable();
|
338 |
-
this.
|
339 |
return this;
|
340 |
}
|
341 |
|
342 |
/**
|
343 |
* Sets an external {@link GpgConfig} to use. Whether it will be used is at
|
344 |
-
* the discretion of the {@link #
|
345 |
*
|
346 |
* @param config
|
347 |
* to set; if {@code null}, the config will be loaded from the
|
|
|
18 |
import org.eclipse.jgit.api.errors.JGitInternalException;
|
19 |
import org.eclipse.jgit.api.errors.NoHeadException;
|
20 |
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
|
|
|
21 |
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
|
22 |
import org.eclipse.jgit.internal.JGitText;
|
23 |
import org.eclipse.jgit.lib.Constants;
|
24 |
import org.eclipse.jgit.lib.GpgConfig;
|
25 |
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
|
|
|
|
|
26 |
import org.eclipse.jgit.lib.ObjectId;
|
27 |
import org.eclipse.jgit.lib.ObjectInserter;
|
28 |
import org.eclipse.jgit.lib.PersonIdent;
|
|
|
30 |
import org.eclipse.jgit.lib.RefUpdate;
|
31 |
import org.eclipse.jgit.lib.RefUpdate.Result;
|
32 |
import org.eclipse.jgit.lib.Repository;
|
33 |
+
import org.eclipse.jgit.lib.Signer;
|
34 |
+
import org.eclipse.jgit.lib.Signers;
|
35 |
import org.eclipse.jgit.lib.TagBuilder;
|
36 |
import org.eclipse.jgit.revwalk.RevObject;
|
37 |
import org.eclipse.jgit.revwalk.RevWalk;
|
|
|
78 |
|
79 |
private GpgConfig gpgConfig;
|
80 |
|
81 |
+
private Signer signer;
|
82 |
|
83 |
private CredentialsProvider credentialsProvider;
|
84 |
|
|
|
132 |
newTag.setTagger(tagger);
|
133 |
newTag.setObjectId(id);
|
134 |
|
135 |
+
if (signer != null) {
|
136 |
+
signer.signObject(repo, gpgConfig, newTag, tagger, signingKey,
|
137 |
+
credentialsProvider);
|
138 |
}
|
139 |
|
140 |
// write the tag object
|
|
|
195 |
*
|
196 |
* @throws InvalidTagNameException
|
197 |
* if the tag name is null or invalid
|
|
|
|
|
198 |
* @throws UnsupportedSigningFormatException
|
199 |
* if the tag should be signed but {@code gpg.format} is not
|
200 |
* {@link GpgFormat#OPENPGP}
|
201 |
*/
|
202 |
private void processOptions()
|
203 |
+
throws InvalidTagNameException, UnsupportedSigningFormatException {
|
|
|
204 |
if (name == null
|
205 |
|| !Repository.isValidRefName(Constants.R_TAGS + name)) {
|
206 |
throw new InvalidTagNameException(
|
|
|
226 |
doSign = gpgConfig.isSignAnnotated();
|
227 |
}
|
228 |
if (doSign) {
|
229 |
+
if (signer == null) {
|
230 |
+
signer = Signers.get(gpgConfig.getKeyFormat());
|
231 |
+
if (signer == null) {
|
232 |
+
throw new UnsupportedSigningFormatException(
|
233 |
+
MessageFormat.format(
|
234 |
+
JGitText.get().signatureTypeUnknown,
|
235 |
+
gpgConfig.getKeyFormat()
|
236 |
+
.toConfigValue()));
|
237 |
}
|
|
|
238 |
}
|
239 |
// The message of a signed tag must end in a newline because
|
240 |
// the signature will be appended.
|
|
|
321 |
}
|
322 |
|
323 |
/**
|
324 |
+
* Sets the {@link Signer} to use if the commit is to be signed.
|
325 |
*
|
326 |
* @param signer
|
327 |
* to use; if {@code null}, the default signer will be used
|
328 |
* @return {@code this}
|
329 |
+
* @since 7.0
|
330 |
*/
|
331 |
+
public TagCommand setSigner(Signer signer) {
|
332 |
checkCallable();
|
333 |
+
this.signer = signer;
|
334 |
return this;
|
335 |
}
|
336 |
|
337 |
/**
|
338 |
* Sets an external {@link GpgConfig} to use. Whether it will be used is at
|
339 |
+
* the discretion of the {@link #setSigner(Signer)}.
|
340 |
*
|
341 |
* @param config
|
342 |
* to set; if {@code null}, the config will be loaded from the
|
@@ -9,7 +9,7 @@
|
|
9 |
*/
|
10 |
package org.eclipse.jgit.api;
|
11 |
|
12 |
-
import org.eclipse.jgit.lib.
|
13 |
import org.eclipse.jgit.revwalk.RevObject;
|
14 |
|
15 |
/**
|
@@ -34,8 +34,9 @@ public interface VerificationResult {
|
|
34 |
* Retrieves the signature verification result.
|
35 |
*
|
36 |
* @return the result, or {@code null}Â if none was computed
|
|
|
37 |
*/
|
38 |
-
|
39 |
|
40 |
/**
|
41 |
* Retrieves the git object of which the signature was verified.
|
|
|
9 |
*/
|
10 |
package org.eclipse.jgit.api;
|
11 |
|
12 |
+
import org.eclipse.jgit.lib.SignatureVerifier;
|
13 |
import org.eclipse.jgit.revwalk.RevObject;
|
14 |
|
15 |
/**
|
|
|
34 |
* Retrieves the signature verification result.
|
35 |
*
|
36 |
* @return the result, or {@code null}Â if none was computed
|
37 |
+
* @since 7.0
|
38 |
*/
|
39 |
+
SignatureVerifier.SignatureVerification getVerification();
|
40 |
|
41 |
/**
|
42 |
* Retrieves the git object of which the signature was verified.
|
@@ -25,11 +25,10 @@
|
|
25 |
import org.eclipse.jgit.internal.JGitText;
|
26 |
import org.eclipse.jgit.lib.Constants;
|
27 |
import org.eclipse.jgit.lib.GpgConfig;
|
28 |
-
import org.eclipse.jgit.lib.GpgSignatureVerifier;
|
29 |
-
import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
|
30 |
-
import org.eclipse.jgit.lib.GpgSignatureVerifierFactory;
|
31 |
import org.eclipse.jgit.lib.ObjectId;
|
32 |
import org.eclipse.jgit.lib.Repository;
|
|
|
|
|
33 |
import org.eclipse.jgit.revwalk.RevObject;
|
34 |
import org.eclipse.jgit.revwalk.RevWalk;
|
35 |
|
@@ -65,12 +64,8 @@ public enum VerifyMode {
|
|
65 |
|
66 |
private VerifyMode mode = VerifyMode.ANY;
|
67 |
|
68 |
-
private GpgSignatureVerifier verifier;
|
69 |
-
|
70 |
private GpgConfig config;
|
71 |
|
72 |
-
private boolean ownVerifier;
|
73 |
-
|
74 |
/**
|
75 |
* Creates a new {@link VerifySignatureCommand} for the given {@link Repository}.
|
76 |
*
|
@@ -140,22 +135,7 @@ public VerifySignatureCommand setMode(@NonNull VerifyMode mode) {
|
|
140 |
}
|
141 |
|
142 |
/**
|
143 |
-
* Sets
|
144 |
-
*
|
145 |
-
* @param verifier
|
146 |
-
* the {@link GpgSignatureVerifier} to use, or {@code null}Â to
|
147 |
-
* use the default verifier
|
148 |
-
* @return {@code this}
|
149 |
-
*/
|
150 |
-
public VerifySignatureCommand setVerifier(GpgSignatureVerifier verifier) {
|
151 |
-
checkCallable();
|
152 |
-
this.verifier = verifier;
|
153 |
-
return this;
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* Sets an external {@link GpgConfig} to use. Whether it will be used it at
|
158 |
-
* the discretion of the {@link #setVerifier(GpgSignatureVerifier)}.
|
159 |
*
|
160 |
* @param config
|
161 |
* to set; if {@code null}, the config will be loaded from the
|
@@ -169,16 +149,6 @@ public VerifySignatureCommand setGpgConfig(GpgConfig config) {
|
|
169 |
return this;
|
170 |
}
|
171 |
|
172 |
-
/**
|
173 |
-
* Retrieves the currently set {@link GpgSignatureVerifier}. Can be used
|
174 |
-
* after a successful {@link #call()} to get the verifier that was used.
|
175 |
-
*
|
176 |
-
* @return the {@link GpgSignatureVerifier}
|
177 |
-
*/
|
178 |
-
public GpgSignatureVerifier getVerifier() {
|
179 |
-
return verifier;
|
180 |
-
}
|
181 |
-
|
182 |
/**
|
183 |
* {@link Repository#resolve(String) Resolves} all names added to the
|
184 |
* command to git objects and verifies their signature. Non-existing objects
|
@@ -193,9 +163,6 @@ public GpgSignatureVerifier getVerifier() {
|
|
193 |
*
|
194 |
* @return a map of the given names to the corresponding
|
195 |
* {@link VerificationResult}, excluding ignored or skipped objects.
|
196 |
-
* @throws ServiceUnavailableException
|
197 |
-
* if no {@link GpgSignatureVerifier} was set and no
|
198 |
-
* {@link GpgSignatureVerifierFactory} is available
|
199 |
* @throws WrongObjectTypeException
|
200 |
* if a name resolves to an object of a type not allowed by the
|
201 |
* {@link #setMode(VerifyMode)} mode
|
@@ -207,16 +174,6 @@ public Map<String, VerificationResult> call()
|
|
207 |
checkCallable();
|
208 |
setCallable(false);
|
209 |
Map<String, VerificationResult> result = new HashMap<>();
|
210 |
-
if (verifier == null) {
|
211 |
-
GpgSignatureVerifierFactory factory = GpgSignatureVerifierFactory
|
212 |
-
.getDefault();
|
213 |
-
if (factory == null) {
|
214 |
-
throw new ServiceUnavailableException(
|
215 |
-
JGitText.get().signatureVerificationUnavailable);
|
216 |
-
}
|
217 |
-
verifier = factory.getVerifier();
|
218 |
-
ownVerifier = true;
|
219 |
-
}
|
220 |
if (config == null) {
|
221 |
config = new GpgConfig(repo.getConfig());
|
222 |
}
|
@@ -239,10 +196,6 @@ public Map<String, VerificationResult> call()
|
|
239 |
} catch (IOException e) {
|
240 |
throw new JGitInternalException(
|
241 |
JGitText.get().signatureVerificationError, e);
|
242 |
-
} finally {
|
243 |
-
if (ownVerifier) {
|
244 |
-
verifier.clear();
|
245 |
-
}
|
246 |
}
|
247 |
return result;
|
248 |
}
|
@@ -258,8 +211,8 @@ private VerificationResult verifyOne(RevObject object)
|
|
258 |
}
|
259 |
if (type == Constants.OBJ_COMMIT || type == Constants.OBJ_TAG) {
|
260 |
try {
|
261 |
-
|
262 |
-
.
|
263 |
if (verification == null) {
|
264 |
// Not signed
|
265 |
return null;
|
|
|
25 |
import org.eclipse.jgit.internal.JGitText;
|
26 |
import org.eclipse.jgit.lib.Constants;
|
27 |
import org.eclipse.jgit.lib.GpgConfig;
|
|
|
|
|
|
|
28 |
import org.eclipse.jgit.lib.ObjectId;
|
29 |
import org.eclipse.jgit.lib.Repository;
|
30 |
+
import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
|
31 |
+
import org.eclipse.jgit.lib.SignatureVerifiers;
|
32 |
import org.eclipse.jgit.revwalk.RevObject;
|
33 |
import org.eclipse.jgit.revwalk.RevWalk;
|
34 |
|
|
|
64 |
|
65 |
private VerifyMode mode = VerifyMode.ANY;
|
66 |
|
|
|
|
|
67 |
private GpgConfig config;
|
68 |
|
|
|
|
|
69 |
/**
|
70 |
* Creates a new {@link VerifySignatureCommand} for the given {@link Repository}.
|
71 |
*
|
|
|
135 |
}
|
136 |
|
137 |
/**
|
138 |
+
* Sets an external {@link GpgConfig} to use.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
*
|
140 |
* @param config
|
141 |
* to set; if {@code null}, the config will be loaded from the
|
|
|
149 |
return this;
|
150 |
}
|
151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
/**
|
153 |
* {@link Repository#resolve(String) Resolves} all names added to the
|
154 |
* command to git objects and verifies their signature. Non-existing objects
|
|
|
163 |
*
|
164 |
* @return a map of the given names to the corresponding
|
165 |
* {@link VerificationResult}, excluding ignored or skipped objects.
|
|
|
|
|
|
|
166 |
* @throws WrongObjectTypeException
|
167 |
* if a name resolves to an object of a type not allowed by the
|
168 |
* {@link #setMode(VerifyMode)} mode
|
|
|
174 |
checkCallable();
|
175 |
setCallable(false);
|
176 |
Map<String, VerificationResult> result = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
if (config == null) {
|
178 |
config = new GpgConfig(repo.getConfig());
|
179 |
}
|
|
|
196 |
} catch (IOException e) {
|
197 |
throw new JGitInternalException(
|
198 |
JGitText.get().signatureVerificationError, e);
|
|
|
|
|
|
|
|
|
199 |
}
|
200 |
return result;
|
201 |
}
|
|
|
211 |
}
|
212 |
if (type == Constants.OBJ_COMMIT || type == Constants.OBJ_TAG) {
|
213 |
try {
|
214 |
+
SignatureVerification verification = SignatureVerifiers
|
215 |
+
.verify(repo, config, object);
|
216 |
if (verification == null) {
|
217 |
// Not signed
|
218 |
return null;
|
@@ -1400,127 +1400,6 @@ private boolean isModifiedSubtree_IndexTree(String path, ObjectId tree)
|
|
1400 |
}
|
1401 |
}
|
1402 |
|
1403 |
-
/**
|
1404 |
-
* Updates the file in the working tree with content and mode from an entry
|
1405 |
-
* in the index. The new content is first written to a new temporary file in
|
1406 |
-
* the same directory as the real file. Then that new file is renamed to the
|
1407 |
-
* final filename.
|
1408 |
-
*
|
1409 |
-
* <p>
|
1410 |
-
* <b>Note:</b> if the entry path on local file system exists as a non-empty
|
1411 |
-
* directory, and the target entry type is a link or file, the checkout will
|
1412 |
-
* fail with {@link java.io.IOException} since existing non-empty directory
|
1413 |
-
* cannot be renamed to file or link without deleting it recursively.
|
1414 |
-
* </p>
|
1415 |
-
*
|
1416 |
-
* @param repo
|
1417 |
-
* repository managing the destination work tree.
|
1418 |
-
* @param entry
|
1419 |
-
* the entry containing new mode and content
|
1420 |
-
* @param or
|
1421 |
-
* object reader to use for checkout
|
1422 |
-
* @throws java.io.IOException
|
1423 |
-
* if an IO error occurred
|
1424 |
-
* @since 3.6
|
1425 |
-
* @deprecated since 5.1, use
|
1426 |
-
* {@link #checkoutEntry(Repository, DirCacheEntry, ObjectReader, boolean, CheckoutMetadata, WorkingTreeOptions)}
|
1427 |
-
* instead
|
1428 |
-
*/
|
1429 |
-
@Deprecated
|
1430 |
-
public static void checkoutEntry(Repository repo, DirCacheEntry entry,
|
1431 |
-
ObjectReader or) throws IOException {
|
1432 |
-
checkoutEntry(repo, entry, or, false, null, null);
|
1433 |
-
}
|
1434 |
-
|
1435 |
-
|
1436 |
-
/**
|
1437 |
-
* Updates the file in the working tree with content and mode from an entry
|
1438 |
-
* in the index. The new content is first written to a new temporary file in
|
1439 |
-
* the same directory as the real file. Then that new file is renamed to the
|
1440 |
-
* final filename.
|
1441 |
-
*
|
1442 |
-
* <p>
|
1443 |
-
* <b>Note:</b> if the entry path on local file system exists as a file, it
|
1444 |
-
* will be deleted and if it exists as a directory, it will be deleted
|
1445 |
-
* recursively, independently if has any content.
|
1446 |
-
* </p>
|
1447 |
-
*
|
1448 |
-
* @param repo
|
1449 |
-
* repository managing the destination work tree.
|
1450 |
-
* @param entry
|
1451 |
-
* the entry containing new mode and content
|
1452 |
-
* @param or
|
1453 |
-
* object reader to use for checkout
|
1454 |
-
* @param deleteRecursive
|
1455 |
-
* true to recursively delete final path if it exists on the file
|
1456 |
-
* system
|
1457 |
-
* @param checkoutMetadata
|
1458 |
-
* containing
|
1459 |
-
* <ul>
|
1460 |
-
* <li>smudgeFilterCommand to be run for smudging the entry to be
|
1461 |
-
* checked out</li>
|
1462 |
-
* <li>eolStreamType used for stream conversion</li>
|
1463 |
-
* </ul>
|
1464 |
-
* @throws java.io.IOException
|
1465 |
-
* if an IO error occurred
|
1466 |
-
* @since 4.2
|
1467 |
-
* @deprecated since 6.3, use
|
1468 |
-
* {@link #checkoutEntry(Repository, DirCacheEntry, ObjectReader, boolean, CheckoutMetadata, WorkingTreeOptions)}
|
1469 |
-
* instead
|
1470 |
-
*/
|
1471 |
-
@Deprecated
|
1472 |
-
public static void checkoutEntry(Repository repo, DirCacheEntry entry,
|
1473 |
-
ObjectReader or, boolean deleteRecursive,
|
1474 |
-
CheckoutMetadata checkoutMetadata) throws IOException {
|
1475 |
-
checkoutEntry(repo, entry, or, deleteRecursive, checkoutMetadata, null);
|
1476 |
-
}
|
1477 |
-
|
1478 |
-
/**
|
1479 |
-
* Updates the file in the working tree with content and mode from an entry
|
1480 |
-
* in the index. The new content is first written to a new temporary file in
|
1481 |
-
* the same directory as the real file. Then that new file is renamed to the
|
1482 |
-
* final filename.
|
1483 |
-
*
|
1484 |
-
* <p>
|
1485 |
-
* <b>Note:</b> if the entry path on local file system exists as a file, it
|
1486 |
-
* will be deleted and if it exists as a directory, it will be deleted
|
1487 |
-
* recursively, independently if has any content.
|
1488 |
-
* </p>
|
1489 |
-
*
|
1490 |
-
* @param repo
|
1491 |
-
* repository managing the destination work tree.
|
1492 |
-
* @param entry
|
1493 |
-
* the entry containing new mode and content
|
1494 |
-
* @param or
|
1495 |
-
* object reader to use for checkout
|
1496 |
-
* @param deleteRecursive
|
1497 |
-
* true to recursively delete final path if it exists on the file
|
1498 |
-
* system
|
1499 |
-
* @param checkoutMetadata
|
1500 |
-
* containing
|
1501 |
-
* <ul>
|
1502 |
-
* <li>smudgeFilterCommand to be run for smudging the entry to be
|
1503 |
-
* checked out</li>
|
1504 |
-
* <li>eolStreamType used for stream conversion</li>
|
1505 |
-
* </ul>
|
1506 |
-
* @param options
|
1507 |
-
* {@link WorkingTreeOptions} that are effective; if {@code null}
|
1508 |
-
* they are loaded from the repository config
|
1509 |
-
* @throws java.io.IOException
|
1510 |
-
* if an IO error occurred
|
1511 |
-
* @since 6.3
|
1512 |
-
* @deprecated since 6.6.1; use {@link Checkout} instead
|
1513 |
-
*/
|
1514 |
-
@Deprecated
|
1515 |
-
public static void checkoutEntry(Repository repo, DirCacheEntry entry,
|
1516 |
-
ObjectReader or, boolean deleteRecursive,
|
1517 |
-
CheckoutMetadata checkoutMetadata, WorkingTreeOptions options)
|
1518 |
-
throws IOException {
|
1519 |
-
Checkout checkout = new Checkout(repo, options)
|
1520 |
-
.setRecursiveDeletion(deleteRecursive);
|
1521 |
-
checkout.checkout(entry, checkoutMetadata, or, null);
|
1522 |
-
}
|
1523 |
-
|
1524 |
/**
|
1525 |
* Return filtered content for a specific object (blob). EOL handling and
|
1526 |
* smudge-filter handling are applied in the same way as it would be done
|
@@ -1647,6 +1526,8 @@ private static void runExternalFilterCommand(Repository repo, String path,
|
|
1647 |
filterProcessBuilder.directory(repo.getWorkTree());
|
1648 |
filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
|
1649 |
repo.getDirectory().getAbsolutePath());
|
|
|
|
|
1650 |
ExecutionResult result;
|
1651 |
int rc;
|
1652 |
try {
|
|
|
1400 |
}
|
1401 |
}
|
1402 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1403 |
/**
|
1404 |
* Return filtered content for a specific object (blob). EOL handling and
|
1405 |
* smudge-filter handling are applied in the same way as it would be done
|
|
|
1526 |
filterProcessBuilder.directory(repo.getWorkTree());
|
1527 |
filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
|
1528 |
repo.getDirectory().getAbsolutePath());
|
1529 |
+
filterProcessBuilder.environment().put(Constants.GIT_COMMON_DIR_KEY,
|
1530 |
+
repo.getCommonDirectory().getAbsolutePath());
|
1531 |
ExecutionResult result;
|
1532 |
int rc;
|
1533 |
try {
|
@@ -386,28 +386,6 @@ void write(OutputStream os, DirCacheVersion version, DirCacheEntry previous)
|
|
386 |
}
|
387 |
}
|
388 |
|
389 |
-
/**
|
390 |
-
* Is it possible for this entry to be accidentally assumed clean?
|
391 |
-
* <p>
|
392 |
-
* The "racy git" problem happens when a work file can be updated faster
|
393 |
-
* than the filesystem records file modification timestamps. It is possible
|
394 |
-
* for an application to edit a work file, update the index, then edit it
|
395 |
-
* again before the filesystem will give the work file a new modification
|
396 |
-
* timestamp. This method tests to see if file was written out at the same
|
397 |
-
* time as the index.
|
398 |
-
*
|
399 |
-
* @param smudge_s
|
400 |
-
* seconds component of the index's last modified time.
|
401 |
-
* @param smudge_ns
|
402 |
-
* nanoseconds component of the index's last modified time.
|
403 |
-
* @return true if extra careful checks should be used.
|
404 |
-
* @deprecated use {@link #mightBeRacilyClean(Instant)} instead
|
405 |
-
*/
|
406 |
-
@Deprecated
|
407 |
-
public final boolean mightBeRacilyClean(int smudge_s, int smudge_ns) {
|
408 |
-
return mightBeRacilyClean(Instant.ofEpochSecond(smudge_s, smudge_ns));
|
409 |
-
}
|
410 |
-
|
411 |
/**
|
412 |
* Is it possible for this entry to be accidentally assumed clean?
|
413 |
* <p>
|
@@ -652,22 +630,6 @@ public void setCreationTime(long when) {
|
|
652 |
encodeTS(P_CTIME, when);
|
653 |
}
|
654 |
|
655 |
-
/**
|
656 |
-
* Get the cached last modification date of this file, in milliseconds.
|
657 |
-
* <p>
|
658 |
-
* One of the indicators that the file has been modified by an application
|
659 |
-
* changing the working tree is if the last modification time for the file
|
660 |
-
* differs from the time stored in this entry.
|
661 |
-
*
|
662 |
-
* @return last modification time of this file, in milliseconds since the
|
663 |
-
* Java epoch (midnight Jan 1, 1970 UTC).
|
664 |
-
* @deprecated use {@link #getLastModifiedInstant()} instead
|
665 |
-
*/
|
666 |
-
@Deprecated
|
667 |
-
public long getLastModified() {
|
668 |
-
return decodeTS(P_MTIME);
|
669 |
-
}
|
670 |
-
|
671 |
/**
|
672 |
* Get the cached last modification date of this file.
|
673 |
* <p>
|
@@ -682,18 +644,6 @@ public Instant getLastModifiedInstant() {
|
|
682 |
return decodeTSInstant(P_MTIME);
|
683 |
}
|
684 |
|
685 |
-
/**
|
686 |
-
* Set the cached last modification date of this file, using milliseconds.
|
687 |
-
*
|
688 |
-
* @param when
|
689 |
-
* new cached modification date of the file, in milliseconds.
|
690 |
-
* @deprecated use {@link #setLastModified(Instant)} instead
|
691 |
-
*/
|
692 |
-
@Deprecated
|
693 |
-
public void setLastModified(long when) {
|
694 |
-
encodeTS(P_MTIME, when);
|
695 |
-
}
|
696 |
-
|
697 |
/**
|
698 |
* Set the cached last modification date of this file.
|
699 |
*
|
|
|
386 |
}
|
387 |
}
|
388 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
389 |
/**
|
390 |
* Is it possible for this entry to be accidentally assumed clean?
|
391 |
* <p>
|
|
|
630 |
encodeTS(P_CTIME, when);
|
631 |
}
|
632 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
633 |
/**
|
634 |
* Get the cached last modification date of this file.
|
635 |
* <p>
|
|
|
644 |
return decodeTSInstant(P_MTIME);
|
645 |
}
|
646 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
/**
|
648 |
* Set the cached last modification date of this file.
|
649 |
*
|
@@ -22,18 +22,6 @@
|
|
22 |
public class PackInvalidException extends IOException {
|
23 |
private static final long serialVersionUID = 1L;
|
24 |
|
25 |
-
/**
|
26 |
-
* Construct a pack invalid error.
|
27 |
-
*
|
28 |
-
* @param path
|
29 |
-
* path of the invalid pack file.
|
30 |
-
* @deprecated Use {@link #PackInvalidException(File, Throwable)}.
|
31 |
-
*/
|
32 |
-
@Deprecated
|
33 |
-
public PackInvalidException(File path) {
|
34 |
-
this(path, null);
|
35 |
-
}
|
36 |
-
|
37 |
/**
|
38 |
* Construct a pack invalid error with cause.
|
39 |
*
|
@@ -47,18 +35,6 @@ public PackInvalidException(File path, Throwable cause) {
|
|
47 |
this(path.getAbsolutePath(), cause);
|
48 |
}
|
49 |
|
50 |
-
/**
|
51 |
-
* Construct a pack invalid error.
|
52 |
-
*
|
53 |
-
* @param path
|
54 |
-
* path of the invalid pack file.
|
55 |
-
* @deprecated Use {@link #PackInvalidException(String, Throwable)}.
|
56 |
-
*/
|
57 |
-
@Deprecated
|
58 |
-
public PackInvalidException(String path) {
|
59 |
-
this(path, null);
|
60 |
-
}
|
61 |
-
|
62 |
/**
|
63 |
* Construct a pack invalid error with cause.
|
64 |
*
|
|
|
22 |
public class PackInvalidException extends IOException {
|
23 |
private static final long serialVersionUID = 1L;
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
* Construct a pack invalid error with cause.
|
27 |
*
|
|
|
35 |
this(path.getAbsolutePath(), cause);
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
/**
|
39 |
* Construct a pack invalid error with cause.
|
40 |
*
|
@@ -156,6 +156,9 @@ private void prepareIndex(List<RepoProject> projects, DirCache index,
|
|
156 |
ObjectId objectId;
|
157 |
if (ObjectId.isId(proj.getRevision())) {
|
158 |
objectId = ObjectId.fromString(proj.getRevision());
|
|
|
|
|
|
|
159 |
} else {
|
160 |
objectId = callback.sha1(url, proj.getRevision());
|
161 |
if (objectId == null && !config.ignoreRemoteFailures) {
|
|
|
156 |
ObjectId objectId;
|
157 |
if (ObjectId.isId(proj.getRevision())) {
|
158 |
objectId = ObjectId.fromString(proj.getRevision());
|
159 |
+
if (config.recordRemoteBranch && proj.getUpstream() != null) {
|
160 |
+
cfg.setString("submodule", name, "ref", proj.getUpstream()); //$NON-NLS-1$//$NON-NLS-2$
|
161 |
+
}
|
162 |
} else {
|
163 |
objectId = callback.sha1(url, proj.getRevision());
|
164 |
if (objectId == null && !config.ignoreRemoteFailures) {
|
@@ -176,6 +176,10 @@ public void startElement(
|
|
176 |
attributes.getValue("groups"));
|
177 |
currentProject
|
178 |
.setRecommendShallow(attributes.getValue("clone-depth"));
|
|
|
|
|
|
|
|
|
179 |
break;
|
180 |
case "remote":
|
181 |
String alias = attributes.getValue("alias");
|
|
|
176 |
attributes.getValue("groups"));
|
177 |
currentProject
|
178 |
.setRecommendShallow(attributes.getValue("clone-depth"));
|
179 |
+
currentProject
|
180 |
+
.setUpstream(attributes.getValue("upstream"));
|
181 |
+
currentProject
|
182 |
+
.setDestBranch(attributes.getValue("dest-branch"));
|
183 |
break;
|
184 |
case "remote":
|
185 |
String alias = attributes.getValue("alias");
|
@@ -110,32 +110,6 @@ public interface RemoteReader {
|
|
110 |
@Nullable
|
111 |
public ObjectId sha1(String uri, String ref) throws GitAPIException;
|
112 |
|
113 |
-
/**
|
114 |
-
* Read a file from a remote repository.
|
115 |
-
*
|
116 |
-
* @param uri
|
117 |
-
* The URI of the remote repository
|
118 |
-
* @param ref
|
119 |
-
* The ref (branch/tag/etc.) to read
|
120 |
-
* @param path
|
121 |
-
* The relative path (inside the repo) to the file to read
|
122 |
-
* @return the file content.
|
123 |
-
* @throws GitAPIException
|
124 |
-
* If the ref have an invalid or ambiguous name, or it does
|
125 |
-
* not exist in the repository,
|
126 |
-
* @throws IOException
|
127 |
-
* If the object does not exist or is too large
|
128 |
-
* @since 3.5
|
129 |
-
*
|
130 |
-
* @deprecated Use {@link #readFileWithMode(String, String, String)}
|
131 |
-
* instead
|
132 |
-
*/
|
133 |
-
@Deprecated
|
134 |
-
public default byte[] readFile(String uri, String ref, String path)
|
135 |
-
throws GitAPIException, IOException {
|
136 |
-
return readFileWithMode(uri, ref, path).getContents();
|
137 |
-
}
|
138 |
-
|
139 |
/**
|
140 |
* Read contents and mode (i.e. permissions) of the file from a remote
|
141 |
* repository.
|
@@ -255,7 +229,8 @@ public RemoteFile readFileWithMode(String uri, String ref, String path)
|
|
255 |
@SuppressWarnings("serial")
|
256 |
static class ManifestErrorException extends GitAPIException {
|
257 |
ManifestErrorException(Throwable cause) {
|
258 |
-
super(RepoText.get().invalidManifest
|
|
|
259 |
}
|
260 |
}
|
261 |
|
@@ -615,6 +590,7 @@ private List<RepoProject> renameProjects(List<RepoProject> projects) {
|
|
615 |
p.setUrl(proj.getUrl());
|
616 |
p.addCopyFiles(proj.getCopyFiles());
|
617 |
p.addLinkFiles(proj.getLinkFiles());
|
|
|
618 |
ret.add(p);
|
619 |
}
|
620 |
}
|
|
|
110 |
@Nullable
|
111 |
public ObjectId sha1(String uri, String ref) throws GitAPIException;
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
/**
|
114 |
* Read contents and mode (i.e. permissions) of the file from a remote
|
115 |
* repository.
|
|
|
229 |
@SuppressWarnings("serial")
|
230 |
static class ManifestErrorException extends GitAPIException {
|
231 |
ManifestErrorException(Throwable cause) {
|
232 |
+
super(RepoText.get().invalidManifest + " " + cause.getMessage(), //$NON-NLS-1$
|
233 |
+
cause);
|
234 |
}
|
235 |
}
|
236 |
|
|
|
590 |
p.setUrl(proj.getUrl());
|
591 |
p.addCopyFiles(proj.getCopyFiles());
|
592 |
p.addLinkFiles(proj.getLinkFiles());
|
593 |
+
p.setUpstream(proj.getUpstream());
|
594 |
ret.add(p);
|
595 |
}
|
596 |
}
|
@@ -38,6 +38,8 @@ public class RepoProject implements Comparable<RepoProject> {
|
|
38 |
private final Set<String> groups;
|
39 |
private final List<CopyFile> copyfiles;
|
40 |
private final List<LinkFile> linkfiles;
|
|
|
|
|
41 |
private String recommendShallow;
|
42 |
private String url;
|
43 |
private String defaultRevision;
|
@@ -389,6 +391,57 @@ public void clearLinkFiles() {
|
|
389 |
this.linkfiles.clear();
|
390 |
}
|
391 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
392 |
private String getPathWithSlash() {
|
393 |
if (path.endsWith("/")) { //$NON-NLS-1$
|
394 |
return path;
|
|
|
38 |
private final Set<String> groups;
|
39 |
private final List<CopyFile> copyfiles;
|
40 |
private final List<LinkFile> linkfiles;
|
41 |
+
private String upstream;
|
42 |
+
private String destBranch;
|
43 |
private String recommendShallow;
|
44 |
private String url;
|
45 |
private String defaultRevision;
|
|
|
391 |
this.linkfiles.clear();
|
392 |
}
|
393 |
|
394 |
+
/**
|
395 |
+
* Return the upstream attribute of the project
|
396 |
+
*
|
397 |
+
* @return the upstream value if present, null otherwise.
|
398 |
+
*
|
399 |
+
* @since 6.10
|
400 |
+
*/
|
401 |
+
public String getUpstream() {
|
402 |
+
return this.upstream;
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Return the dest-branch attribute of the project
|
407 |
+
*
|
408 |
+
* @return the dest-branch value if present, null otherwise.
|
409 |
+
*
|
410 |
+
* @since 6.10
|
411 |
+
*/
|
412 |
+
public String getDestBranch() {
|
413 |
+
return this.destBranch;
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Set the upstream attribute of the project
|
418 |
+
*
|
419 |
+
* Name of the git ref in which a sha1 can be found, when the revision is a
|
420 |
+
* sha1.
|
421 |
+
*
|
422 |
+
* @param upstream
|
423 |
+
* value of the attribute in the manifest
|
424 |
+
*
|
425 |
+
* @since 6.10
|
426 |
+
*/
|
427 |
+
public void setUpstream(String upstream) {
|
428 |
+
this.upstream = upstream;
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Set the dest-branch attribute of the project
|
433 |
+
*
|
434 |
+
* Name of a Git branch.
|
435 |
+
*
|
436 |
+
* @param destBranch
|
437 |
+
* value of the attribute in the manifest
|
438 |
+
*
|
439 |
+
* @since 6.10
|
440 |
+
*/
|
441 |
+
public void setDestBranch(String destBranch) {
|
442 |
+
this.destBranch = destBranch;
|
443 |
+
}
|
444 |
+
|
445 |
private String getPathWithSlash() {
|
446 |
if (path.endsWith("/")) { //$NON-NLS-1$
|
447 |
return path;
|
@@ -315,6 +315,9 @@ public static JGitText get() {
|
|
315 |
/***/ public String downloadCancelled;
|
316 |
/***/ public String downloadCancelledDuringIndexing;
|
317 |
/***/ public String duplicateAdvertisementsOf;
|
|
|
|
|
|
|
318 |
/***/ public String duplicateRef;
|
319 |
/***/ public String duplicateRefAttribute;
|
320 |
/***/ public String duplicateRemoteRefUpdateIsIllegal;
|
@@ -569,6 +572,8 @@ public static JGitText get() {
|
|
569 |
/***/ public String noMergeHeadSpecified;
|
570 |
/***/ public String nonBareLinkFilesNotSupported;
|
571 |
/***/ public String nonCommitToHeads;
|
|
|
|
|
572 |
/***/ public String noPathAttributesFound;
|
573 |
/***/ public String noSuchRef;
|
574 |
/***/ public String noSuchRefKnown;
|
@@ -601,7 +606,6 @@ public static JGitText get() {
|
|
601 |
/***/ public String oldIdMustNotBeNull;
|
602 |
/***/ public String onlyOneFetchSupported;
|
603 |
/***/ public String onlyOneOperationCallPerConnectionIsSupported;
|
604 |
-
/***/ public String onlyOpenPgpSupportedForSigning;
|
605 |
/***/ public String openFilesMustBeAtLeast1;
|
606 |
/***/ public String openingConnection;
|
607 |
/***/ public String operationCanceled;
|
@@ -747,6 +751,8 @@ public static JGitText get() {
|
|
747 |
/***/ public String shutdownCleanup;
|
748 |
/***/ public String shutdownCleanupFailed;
|
749 |
/***/ public String shutdownCleanupListenerFailed;
|
|
|
|
|
750 |
/***/ public String signatureVerificationError;
|
751 |
/***/ public String signatureVerificationUnavailable;
|
752 |
/***/ public String signedTagMessageNoLf;
|
@@ -833,6 +839,7 @@ public static JGitText get() {
|
|
833 |
/***/ public String unableToCheckConnectivity;
|
834 |
/***/ public String unableToCreateNewObject;
|
835 |
/***/ public String unableToReadFullInt;
|
|
|
836 |
/***/ public String unableToReadPackfile;
|
837 |
/***/ public String unableToRemovePath;
|
838 |
/***/ public String unableToWrite;
|
@@ -858,6 +865,7 @@ public static JGitText get() {
|
|
858 |
/***/ public String unknownObjectInIndex;
|
859 |
/***/ public String unknownObjectType;
|
860 |
/***/ public String unknownObjectType2;
|
|
|
861 |
/***/ public String unknownPositionEncoding;
|
862 |
/***/ public String unknownRefStorageFormat;
|
863 |
/***/ public String unknownRepositoryFormat;
|
|
|
315 |
/***/ public String downloadCancelled;
|
316 |
/***/ public String downloadCancelledDuringIndexing;
|
317 |
/***/ public String duplicateAdvertisementsOf;
|
318 |
+
/***/ public String duplicateCacheTablesGiven;
|
319 |
+
/***/ public String duplicatePackExtensionsForCacheTables;
|
320 |
+
/***/ public String duplicatePackExtensionsSet;
|
321 |
/***/ public String duplicateRef;
|
322 |
/***/ public String duplicateRefAttribute;
|
323 |
/***/ public String duplicateRemoteRefUpdateIsIllegal;
|
|
|
572 |
/***/ public String noMergeHeadSpecified;
|
573 |
/***/ public String nonBareLinkFilesNotSupported;
|
574 |
/***/ public String nonCommitToHeads;
|
575 |
+
/***/ public String noPackExtConfigurationGiven;
|
576 |
+
/***/ public String noPackExtGivenForConfiguration;
|
577 |
/***/ public String noPathAttributesFound;
|
578 |
/***/ public String noSuchRef;
|
579 |
/***/ public String noSuchRefKnown;
|
|
|
606 |
/***/ public String oldIdMustNotBeNull;
|
607 |
/***/ public String onlyOneFetchSupported;
|
608 |
/***/ public String onlyOneOperationCallPerConnectionIsSupported;
|
|
|
609 |
/***/ public String openFilesMustBeAtLeast1;
|
610 |
/***/ public String openingConnection;
|
611 |
/***/ public String operationCanceled;
|
|
|
751 |
/***/ public String shutdownCleanup;
|
752 |
/***/ public String shutdownCleanupFailed;
|
753 |
/***/ public String shutdownCleanupListenerFailed;
|
754 |
+
/***/ public String signatureServiceConflict;
|
755 |
+
/***/ public String signatureTypeUnknown;
|
756 |
/***/ public String signatureVerificationError;
|
757 |
/***/ public String signatureVerificationUnavailable;
|
758 |
/***/ public String signedTagMessageNoLf;
|
|
|
839 |
/***/ public String unableToCheckConnectivity;
|
840 |
/***/ public String unableToCreateNewObject;
|
841 |
/***/ public String unableToReadFullInt;
|
842 |
+
/***/ public String unableToReadFullArray;
|
843 |
/***/ public String unableToReadPackfile;
|
844 |
/***/ public String unableToRemovePath;
|
845 |
/***/ public String unableToWrite;
|
|
|
865 |
/***/ public String unknownObjectInIndex;
|
866 |
/***/ public String unknownObjectType;
|
867 |
/***/ public String unknownObjectType2;
|
868 |
+
/***/ public String unknownPackExtension;
|
869 |
/***/ public String unknownPositionEncoding;
|
870 |
/***/ public String unknownRefStorageFormat;
|
871 |
/***/ public String unknownRepositoryFormat;
|
@@ -52,6 +52,7 @@
|
|
52 |
import org.eclipse.jgit.revwalk.RevWalk;
|
53 |
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
|
54 |
import org.eclipse.jgit.treewalk.TreeWalk;
|
|
|
55 |
import org.eclipse.jgit.util.NB;
|
56 |
|
57 |
/**
|
@@ -71,6 +72,9 @@ public class CommitGraphWriter {
|
|
71 |
|
72 |
private static final int MAX_CHANGED_PATHS = 512;
|
73 |
|
|
|
|
|
|
|
74 |
private final int hashsz;
|
75 |
|
76 |
private final GraphCommits graphCommits;
|
@@ -374,37 +378,6 @@ private int[] computeGenerationNumbers(ProgressMonitor monitor)
|
|
374 |
return generations;
|
375 |
}
|
376 |
|
377 |
-
private static Optional<HashSet<ByteBuffer>> computeBloomFilterPaths(
|
378 |
-
ObjectReader or, RevCommit cmit) throws MissingObjectException,
|
379 |
-
IncorrectObjectTypeException, CorruptObjectException, IOException {
|
380 |
-
HashSet<ByteBuffer> paths = new HashSet<>();
|
381 |
-
try (TreeWalk walk = new TreeWalk(null, or)) {
|
382 |
-
walk.setRecursive(true);
|
383 |
-
if (cmit.getParentCount() == 0) {
|
384 |
-
walk.addTree(new EmptyTreeIterator());
|
385 |
-
} else {
|
386 |
-
walk.addTree(cmit.getParent(0).getTree());
|
387 |
-
}
|
388 |
-
walk.addTree(cmit.getTree());
|
389 |
-
while (walk.next()) {
|
390 |
-
if (walk.idEqual(0, 1)) {
|
391 |
-
continue;
|
392 |
-
}
|
393 |
-
byte[] rawPath = walk.getRawPath();
|
394 |
-
paths.add(ByteBuffer.wrap(rawPath));
|
395 |
-
for (int i = 0; i < rawPath.length; i++) {
|
396 |
-
if (rawPath[i] == '/') {
|
397 |
-
paths.add(ByteBuffer.wrap(rawPath, 0, i));
|
398 |
-
}
|
399 |
-
if (paths.size() > MAX_CHANGED_PATHS) {
|
400 |
-
return Optional.empty();
|
401 |
-
}
|
402 |
-
}
|
403 |
-
}
|
404 |
-
}
|
405 |
-
return Optional.of(paths);
|
406 |
-
}
|
407 |
-
|
408 |
private BloomFilterChunks computeBloomFilterChunks(ProgressMonitor monitor)
|
409 |
throws MissingObjectException, IncorrectObjectTypeException,
|
410 |
CorruptObjectException, IOException {
|
@@ -435,8 +408,8 @@ private BloomFilterChunks computeBloomFilterChunks(ProgressMonitor monitor)
|
|
435 |
filtersReused++;
|
436 |
} else {
|
437 |
filtersComputed++;
|
438 |
-
Optional<HashSet<ByteBuffer>> paths =
|
439 |
-
graphCommits.getObjectReader(), cmit);
|
440 |
if (paths.isEmpty()) {
|
441 |
cpf = ChangedPathFilter.FULL;
|
442 |
} else {
|
@@ -473,6 +446,44 @@ private void writeExtraEdges(CancellableDigestOutputStream out)
|
|
473 |
}
|
474 |
}
|
475 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
476 |
private static class ChunkHeader {
|
477 |
final int id;
|
478 |
|
|
|
52 |
import org.eclipse.jgit.revwalk.RevWalk;
|
53 |
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
|
54 |
import org.eclipse.jgit.treewalk.TreeWalk;
|
55 |
+
import org.eclipse.jgit.treewalk.filter.TreeFilter;
|
56 |
import org.eclipse.jgit.util.NB;
|
57 |
|
58 |
/**
|
|
|
72 |
|
73 |
private static final int MAX_CHANGED_PATHS = 512;
|
74 |
|
75 |
+
private static final PathDiffCalculator PATH_DIFF_CALCULATOR
|
76 |
+
= new PathDiffCalculator();
|
77 |
+
|
78 |
private final int hashsz;
|
79 |
|
80 |
private final GraphCommits graphCommits;
|
|
|
378 |
return generations;
|
379 |
}
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
private BloomFilterChunks computeBloomFilterChunks(ProgressMonitor monitor)
|
382 |
throws MissingObjectException, IncorrectObjectTypeException,
|
383 |
CorruptObjectException, IOException {
|
|
|
408 |
filtersReused++;
|
409 |
} else {
|
410 |
filtersComputed++;
|
411 |
+
Optional<HashSet<ByteBuffer>> paths = PATH_DIFF_CALCULATOR
|
412 |
+
.changedPaths(graphCommits.getObjectReader(), cmit);
|
413 |
if (paths.isEmpty()) {
|
414 |
cpf = ChangedPathFilter.FULL;
|
415 |
} else {
|
|
|
446 |
}
|
447 |
}
|
448 |
|
449 |
+
// Visible for testing
|
450 |
+
static class PathDiffCalculator {
|
451 |
+
|
452 |
+
// Walk steps in the last invocation of changedPaths
|
453 |
+
int stepCounter;
|
454 |
+
|
455 |
+
Optional<HashSet<ByteBuffer>> changedPaths(
|
456 |
+
ObjectReader or, RevCommit cmit) throws MissingObjectException,
|
457 |
+
IncorrectObjectTypeException, CorruptObjectException, IOException {
|
458 |
+
stepCounter = 0;
|
459 |
+
HashSet<ByteBuffer> paths = new HashSet<>();
|
460 |
+
try (TreeWalk walk = new TreeWalk(null, or)) {
|
461 |
+
walk.setRecursive(true);
|
462 |
+
walk.setFilter(TreeFilter.ANY_DIFF);
|
463 |
+
if (cmit.getParentCount() == 0) {
|
464 |
+
walk.addTree(new EmptyTreeIterator());
|
465 |
+
} else {
|
466 |
+
walk.addTree(cmit.getParent(0).getTree());
|
467 |
+
}
|
468 |
+
walk.addTree(cmit.getTree());
|
469 |
+
while (walk.next()) {
|
470 |
+
stepCounter += 1;
|
471 |
+
byte[] rawPath = walk.getRawPath();
|
472 |
+
paths.add(ByteBuffer.wrap(rawPath));
|
473 |
+
for (int i = 0; i < rawPath.length; i++) {
|
474 |
+
if (rawPath[i] == '/') {
|
475 |
+
paths.add(ByteBuffer.wrap(rawPath, 0, i));
|
476 |
+
}
|
477 |
+
if (paths.size() > MAX_CHANGED_PATHS) {
|
478 |
+
return Optional.empty();
|
479 |
+
}
|
480 |
+
}
|
481 |
+
}
|
482 |
+
}
|
483 |
+
return Optional.of(paths);
|
484 |
+
}
|
485 |
+
}
|
486 |
+
|
487 |
private static class ChunkHeader {
|
488 |
final int id;
|
489 |
|
@@ -135,7 +135,7 @@ final class ClockBlockCacheTable implements DfsBlockCacheTable {
|
|
135 |
}
|
136 |
|
137 |
@Override
|
138 |
-
public
|
139 |
return dfsBlockCacheStats;
|
140 |
}
|
141 |
|
|
|
135 |
}
|
136 |
|
137 |
@Override
|
138 |
+
public BlockCacheStats getBlockCacheStats() {
|
139 |
return dfsBlockCacheStats;
|
140 |
}
|
141 |
|
@@ -119,7 +119,7 @@ boolean shouldCopyThroughCache(long length) {
|
|
119 |
* @return total number of bytes in the cache, per pack file extension.
|
120 |
*/
|
121 |
public long[] getCurrentSize() {
|
122 |
-
return dfsBlockCacheTable.
|
123 |
}
|
124 |
|
125 |
/**
|
@@ -138,7 +138,7 @@ public long getFillPercentage() {
|
|
138 |
* extension.
|
139 |
*/
|
140 |
public long[] getHitCount() {
|
141 |
-
return dfsBlockCacheTable.
|
142 |
}
|
143 |
|
144 |
/**
|
@@ -149,7 +149,7 @@ public long[] getHitCount() {
|
|
149 |
* extension.
|
150 |
*/
|
151 |
public long[] getMissCount() {
|
152 |
-
return dfsBlockCacheTable.
|
153 |
}
|
154 |
|
155 |
/**
|
@@ -158,7 +158,7 @@ public long[] getMissCount() {
|
|
158 |
* @return total number of requests (hit + miss), per pack file extension.
|
159 |
*/
|
160 |
public long[] getTotalRequestCount() {
|
161 |
-
return dfsBlockCacheTable.
|
162 |
.getTotalRequestCount();
|
163 |
}
|
164 |
|
@@ -168,7 +168,7 @@ public long[] getTotalRequestCount() {
|
|
168 |
* @return hit ratios
|
169 |
*/
|
170 |
public long[] getHitRatio() {
|
171 |
-
return dfsBlockCacheTable.
|
172 |
}
|
173 |
|
174 |
/**
|
@@ -179,7 +179,7 @@ public long[] getHitRatio() {
|
|
179 |
* file extension.
|
180 |
*/
|
181 |
public long[] getEvictions() {
|
182 |
-
return dfsBlockCacheTable.
|
183 |
}
|
184 |
|
185 |
/**
|
|
|
119 |
* @return total number of bytes in the cache, per pack file extension.
|
120 |
*/
|
121 |
public long[] getCurrentSize() {
|
122 |
+
return dfsBlockCacheTable.getBlockCacheStats().getCurrentSize();
|
123 |
}
|
124 |
|
125 |
/**
|
|
|
138 |
* extension.
|
139 |
*/
|
140 |
public long[] getHitCount() {
|
141 |
+
return dfsBlockCacheTable.getBlockCacheStats().getHitCount();
|
142 |
}
|
143 |
|
144 |
/**
|
|
|
149 |
* extension.
|
150 |
*/
|
151 |
public long[] getMissCount() {
|
152 |
+
return dfsBlockCacheTable.getBlockCacheStats().getMissCount();
|
153 |
}
|
154 |
|
155 |
/**
|
|
|
158 |
* @return total number of requests (hit + miss), per pack file extension.
|
159 |
*/
|
160 |
public long[] getTotalRequestCount() {
|
161 |
+
return dfsBlockCacheTable.getBlockCacheStats()
|
162 |
.getTotalRequestCount();
|
163 |
}
|
164 |
|
|
|
168 |
* @return hit ratios
|
169 |
*/
|
170 |
public long[] getHitRatio() {
|
171 |
+
return dfsBlockCacheTable.getBlockCacheStats().getHitRatio();
|
172 |
}
|
173 |
|
174 |
/**
|
|
|
179 |
* file extension.
|
180 |
*/
|
181 |
public long[] getEvictions() {
|
182 |
+
return dfsBlockCacheTable.getBlockCacheStats().getEvictions();
|
183 |
}
|
184 |
|
185 |
/**
|
@@ -11,17 +11,25 @@
|
|
11 |
package org.eclipse.jgit.internal.storage.dfs;
|
12 |
|
13 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
|
|
|
14 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_SECTION;
|
15 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_LIMIT;
|
16 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_SIZE;
|
17 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONCURRENCY_LEVEL;
|
|
|
18 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_RATIO;
|
19 |
|
20 |
import java.text.MessageFormat;
|
21 |
import java.time.Duration;
|
|
|
22 |
import java.util.Collections;
|
|
|
|
|
|
|
23 |
import java.util.Map;
|
|
|
24 |
import java.util.function.Consumer;
|
|
|
25 |
|
26 |
import org.eclipse.jgit.internal.JGitText;
|
27 |
import org.eclipse.jgit.internal.storage.pack.PackExt;
|
@@ -42,15 +50,21 @@ public class DfsBlockCacheConfig {
|
|
42 |
public static final int DEFAULT_CACHE_HOT_MAX = 1;
|
43 |
|
44 |
private long blockLimit;
|
|
|
45 |
private int blockSize;
|
|
|
46 |
private double streamRatio;
|
|
|
47 |
private int concurrencyLevel;
|
48 |
|
49 |
private Consumer<Long> refLock;
|
|
|
50 |
private Map<PackExt, Integer> cacheHotMap;
|
51 |
|
52 |
private IndexEventConsumer indexEventConsumer;
|
53 |
|
|
|
|
|
54 |
/**
|
55 |
* Create a default configuration.
|
56 |
*/
|
@@ -60,6 +74,7 @@ public DfsBlockCacheConfig() {
|
|
60 |
setStreamRatio(0.30);
|
61 |
setConcurrencyLevel(32);
|
62 |
cacheHotMap = Collections.emptyMap();
|
|
|
63 |
}
|
64 |
|
65 |
/**
|
@@ -77,10 +92,10 @@ public long getBlockLimit() {
|
|
77 |
* Set maximum number bytes of heap memory to dedicate to caching pack file
|
78 |
* data.
|
79 |
* <p>
|
80 |
-
* It is strongly recommended to set the block limit to be an integer
|
81 |
-
* of the block size. This constraint is not enforced by this
|
82 |
-
* it may be called before {@link #setBlockSize(int)}), but it
|
83 |
-
* {@link #fromConfig(Config)}.
|
84 |
*
|
85 |
* @param newLimit
|
86 |
* maximum number bytes of heap memory to dedicate to caching
|
@@ -89,9 +104,9 @@ public long getBlockLimit() {
|
|
89 |
*/
|
90 |
public DfsBlockCacheConfig setBlockLimit(long newLimit) {
|
91 |
if (newLimit <= 0) {
|
92 |
-
throw new IllegalArgumentException(
|
93 |
-
JGitText.get().blockLimitNotPositive,
|
94 |
-
|
95 |
}
|
96 |
blockLimit = newLimit;
|
97 |
return this;
|
@@ -239,62 +254,116 @@ public DfsBlockCacheConfig setIndexEventConsumer(
|
|
239 |
return this;
|
240 |
}
|
241 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
/**
|
243 |
* Update properties by setting fields from the configuration.
|
244 |
* <p>
|
245 |
* If a property is not defined in the configuration, then it is left
|
246 |
* unmodified.
|
247 |
* <p>
|
248 |
-
* Enforces certain constraints on the combination of settings in the
|
249 |
-
* for example that the block limit is a multiple of the block size.
|
250 |
*
|
251 |
* @param rc
|
252 |
* configuration to read properties from.
|
253 |
* @return {@code this}
|
254 |
*/
|
255 |
public DfsBlockCacheConfig fromConfig(Config rc) {
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
getBlockSize());
|
266 |
if (cfgBlockLimit % cfgBlockSize != 0) {
|
267 |
throw new IllegalArgumentException(MessageFormat.format(
|
268 |
JGitText.get().blockLimitNotMultipleOfBlockSize,
|
269 |
-
Long.valueOf(cfgBlockLimit),
|
270 |
-
Long.valueOf(cfgBlockSize)));
|
271 |
}
|
272 |
|
273 |
setBlockLimit(cfgBlockLimit);
|
274 |
setBlockSize(cfgBlockSize);
|
275 |
|
276 |
-
setConcurrencyLevel(rc.getInt(
|
277 |
-
|
278 |
-
CONFIG_DFS_SECTION,
|
279 |
-
CONFIG_KEY_CONCURRENCY_LEVEL,
|
280 |
-
getConcurrencyLevel()));
|
281 |
|
282 |
-
String v = rc.getString(
|
283 |
-
CONFIG_CORE_SECTION,
|
284 |
-
CONFIG_DFS_SECTION,
|
285 |
-
CONFIG_KEY_STREAM_RATIO);
|
286 |
if (v != null) {
|
287 |
try {
|
288 |
setStreamRatio(Double.parseDouble(v));
|
289 |
} catch (NumberFormatException e) {
|
290 |
throw new IllegalArgumentException(MessageFormat.format(
|
291 |
-
JGitText.get().enumValueNotSupported3,
|
292 |
-
|
293 |
-
CONFIG_DFS_SECTION,
|
294 |
-
CONFIG_KEY_STREAM_RATIO, v), e);
|
295 |
}
|
296 |
}
|
297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
}
|
299 |
|
300 |
/** Consumer of DfsBlockCache loading and eviction events for indexes. */
|
@@ -346,4 +415,88 @@ default boolean shouldReportEvictedEvent() {
|
|
346 |
return false;
|
347 |
}
|
348 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
}
|
|
|
11 |
package org.eclipse.jgit.internal.storage.dfs;
|
12 |
|
13 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
|
14 |
+
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_CACHE_PREFIX;
|
15 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_SECTION;
|
16 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_LIMIT;
|
17 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_SIZE;
|
18 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONCURRENCY_LEVEL;
|
19 |
+
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACK_EXTENSIONS;
|
20 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_RATIO;
|
21 |
|
22 |
import java.text.MessageFormat;
|
23 |
import java.time.Duration;
|
24 |
+
import java.util.ArrayList;
|
25 |
import java.util.Collections;
|
26 |
+
import java.util.EnumSet;
|
27 |
+
import java.util.HashSet;
|
28 |
+
import java.util.List;
|
29 |
import java.util.Map;
|
30 |
+
import java.util.Set;
|
31 |
import java.util.function.Consumer;
|
32 |
+
import java.util.stream.Collectors;
|
33 |
|
34 |
import org.eclipse.jgit.internal.JGitText;
|
35 |
import org.eclipse.jgit.internal.storage.pack.PackExt;
|
|
|
50 |
public static final int DEFAULT_CACHE_HOT_MAX = 1;
|
51 |
|
52 |
private long blockLimit;
|
53 |
+
|
54 |
private int blockSize;
|
55 |
+
|
56 |
private double streamRatio;
|
57 |
+
|
58 |
private int concurrencyLevel;
|
59 |
|
60 |
private Consumer<Long> refLock;
|
61 |
+
|
62 |
private Map<PackExt, Integer> cacheHotMap;
|
63 |
|
64 |
private IndexEventConsumer indexEventConsumer;
|
65 |
|
66 |
+
private List<DfsBlockCachePackExtConfig> packExtCacheConfigurations;
|
67 |
+
|
68 |
/**
|
69 |
* Create a default configuration.
|
70 |
*/
|
|
|
74 |
setStreamRatio(0.30);
|
75 |
setConcurrencyLevel(32);
|
76 |
cacheHotMap = Collections.emptyMap();
|
77 |
+
packExtCacheConfigurations = Collections.emptyList();
|
78 |
}
|
79 |
|
80 |
/**
|
|
|
92 |
* Set maximum number bytes of heap memory to dedicate to caching pack file
|
93 |
* data.
|
94 |
* <p>
|
95 |
+
* It is strongly recommended to set the block limit to be an integer
|
96 |
+
* multiple of the block size. This constraint is not enforced by this
|
97 |
+
* method (since it may be called before {@link #setBlockSize(int)}), but it
|
98 |
+
* is enforced by {@link #fromConfig(Config)}.
|
99 |
*
|
100 |
* @param newLimit
|
101 |
* maximum number bytes of heap memory to dedicate to caching
|
|
|
104 |
*/
|
105 |
public DfsBlockCacheConfig setBlockLimit(long newLimit) {
|
106 |
if (newLimit <= 0) {
|
107 |
+
throw new IllegalArgumentException(
|
108 |
+
MessageFormat.format(JGitText.get().blockLimitNotPositive,
|
109 |
+
Long.valueOf(newLimit)));
|
110 |
}
|
111 |
blockLimit = newLimit;
|
112 |
return this;
|
|
|
254 |
return this;
|
255 |
}
|
256 |
|
257 |
+
/**
|
258 |
+
* Get the list of pack ext cache configs.
|
259 |
+
*
|
260 |
+
* @return the list of pack ext cache configs.
|
261 |
+
*/
|
262 |
+
List<DfsBlockCachePackExtConfig> getPackExtCacheConfigurations() {
|
263 |
+
return packExtCacheConfigurations;
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Set the list of pack ext cache configs.
|
268 |
+
*
|
269 |
+
* Made visible for testing.
|
270 |
+
*
|
271 |
+
* @param packExtCacheConfigurations
|
272 |
+
* the list of pack ext cache configs to set.
|
273 |
+
* @return {@code this}
|
274 |
+
*/
|
275 |
+
DfsBlockCacheConfig setPackExtCacheConfigurations(
|
276 |
+
List<DfsBlockCachePackExtConfig> packExtCacheConfigurations) {
|
277 |
+
this.packExtCacheConfigurations = packExtCacheConfigurations;
|
278 |
+
return this;
|
279 |
+
}
|
280 |
+
|
281 |
/**
|
282 |
* Update properties by setting fields from the configuration.
|
283 |
* <p>
|
284 |
* If a property is not defined in the configuration, then it is left
|
285 |
* unmodified.
|
286 |
* <p>
|
287 |
+
* Enforces certain constraints on the combination of settings in the
|
288 |
+
* config, for example that the block limit is a multiple of the block size.
|
289 |
*
|
290 |
* @param rc
|
291 |
* configuration to read properties from.
|
292 |
* @return {@code this}
|
293 |
*/
|
294 |
public DfsBlockCacheConfig fromConfig(Config rc) {
|
295 |
+
fromConfig(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION, rc);
|
296 |
+
loadPackExtConfigs(rc);
|
297 |
+
return this;
|
298 |
+
}
|
299 |
+
|
300 |
+
private void fromConfig(String section, String subSection, Config rc) {
|
301 |
+
long cfgBlockLimit = rc.getLong(section, subSection,
|
302 |
+
CONFIG_KEY_BLOCK_LIMIT, getBlockLimit());
|
303 |
+
int cfgBlockSize = rc.getInt(section, subSection, CONFIG_KEY_BLOCK_SIZE,
|
304 |
getBlockSize());
|
305 |
if (cfgBlockLimit % cfgBlockSize != 0) {
|
306 |
throw new IllegalArgumentException(MessageFormat.format(
|
307 |
JGitText.get().blockLimitNotMultipleOfBlockSize,
|
308 |
+
Long.valueOf(cfgBlockLimit), Long.valueOf(cfgBlockSize)));
|
|
|
309 |
}
|
310 |
|
311 |
setBlockLimit(cfgBlockLimit);
|
312 |
setBlockSize(cfgBlockSize);
|
313 |
|
314 |
+
setConcurrencyLevel(rc.getInt(section, subSection,
|
315 |
+
CONFIG_KEY_CONCURRENCY_LEVEL, getConcurrencyLevel()));
|
|
|
|
|
|
|
316 |
|
317 |
+
String v = rc.getString(section, subSection, CONFIG_KEY_STREAM_RATIO);
|
|
|
|
|
|
|
318 |
if (v != null) {
|
319 |
try {
|
320 |
setStreamRatio(Double.parseDouble(v));
|
321 |
} catch (NumberFormatException e) {
|
322 |
throw new IllegalArgumentException(MessageFormat.format(
|
323 |
+
JGitText.get().enumValueNotSupported3, section,
|
324 |
+
subSection, CONFIG_KEY_STREAM_RATIO, v), e);
|
|
|
|
|
325 |
}
|
326 |
}
|
327 |
+
}
|
328 |
+
|
329 |
+
private void loadPackExtConfigs(Config config) {
|
330 |
+
List<String> subSections = config.getSubsections(CONFIG_CORE_SECTION)
|
331 |
+
.stream()
|
332 |
+
.filter(section -> section.startsWith(CONFIG_DFS_CACHE_PREFIX))
|
333 |
+
.collect(Collectors.toList());
|
334 |
+
if (subSections.size() == 0) {
|
335 |
+
return;
|
336 |
+
}
|
337 |
+
ArrayList<DfsBlockCachePackExtConfig> cacheConfigs = new ArrayList<>();
|
338 |
+
Set<PackExt> extensionsSeen = new HashSet<>();
|
339 |
+
for (String subSection : subSections) {
|
340 |
+
var cacheConfig = DfsBlockCachePackExtConfig.fromConfig(config,
|
341 |
+
CONFIG_CORE_SECTION, subSection);
|
342 |
+
Set<PackExt> packExtsDuplicates = intersection(extensionsSeen,
|
343 |
+
cacheConfig.packExts);
|
344 |
+
if (packExtsDuplicates.size() > 0) {
|
345 |
+
String duplicatePackExts = packExtsDuplicates.stream()
|
346 |
+
.map(PackExt::toString)
|
347 |
+
.collect(Collectors.joining(",")); //$NON-NLS-1$
|
348 |
+
throw new IllegalArgumentException(MessageFormat.format(
|
349 |
+
JGitText.get().duplicatePackExtensionsSet,
|
350 |
+
CONFIG_CORE_SECTION, subSection,
|
351 |
+
CONFIG_KEY_PACK_EXTENSIONS, duplicatePackExts));
|
352 |
+
}
|
353 |
+
extensionsSeen.addAll(cacheConfig.packExts);
|
354 |
+
cacheConfigs.add(cacheConfig);
|
355 |
+
}
|
356 |
+
packExtCacheConfigurations = cacheConfigs;
|
357 |
+
}
|
358 |
+
|
359 |
+
private static <T> Set<T> intersection(Set<T> first, Set<T> second) {
|
360 |
+
Set<T> ret = new HashSet<>();
|
361 |
+
for (T entry : second) {
|
362 |
+
if (first.contains(entry)) {
|
363 |
+
ret.add(entry);
|
364 |
+
}
|
365 |
+
}
|
366 |
+
return ret;
|
367 |
}
|
368 |
|
369 |
/** Consumer of DfsBlockCache loading and eviction events for indexes. */
|
|
|
415 |
return false;
|
416 |
}
|
417 |
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* A configuration for a single cache table storing 1 or more Pack
|
421 |
+
* extensions.
|
422 |
+
* <p>
|
423 |
+
* The current pack ext cache tables implementation supports the same
|
424 |
+
* parameters the ClockBlockCacheTable (current default implementation).
|
425 |
+
* <p>
|
426 |
+
* Configuration falls back to the defaults coded values defined in the
|
427 |
+
* {@link DfsBlockCacheConfig} when not set on each cache table
|
428 |
+
* configuration and NOT the values of the basic dfs section.
|
429 |
+
* <p>
|
430 |
+
* <code>
|
431 |
+
*
|
432 |
+
* Format:
|
433 |
+
* [core "dfs.packCache"]
|
434 |
+
* packExtensions = "PACK"
|
435 |
+
* blockSize = 512
|
436 |
+
* blockLimit = 100
|
437 |
+
* concurrencyLevel = 5
|
438 |
+
*
|
439 |
+
* [core "dfs.multipleExtensionCache"]
|
440 |
+
* packExtensions = "INDEX REFTABLE BITMAP_INDEX"
|
441 |
+
* blockSize = 512
|
442 |
+
* blockLimit = 100
|
443 |
+
* concurrencyLevel = 5
|
444 |
+
* </code>
|
445 |
+
*/
|
446 |
+
static class DfsBlockCachePackExtConfig {
|
447 |
+
// Set of pack extensions that will map to the cache instance.
|
448 |
+
private final EnumSet<PackExt> packExts;
|
449 |
+
|
450 |
+
// Configuration for the cache instance.
|
451 |
+
private final DfsBlockCacheConfig packExtCacheConfiguration;
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Made visible for testing.
|
455 |
+
*
|
456 |
+
* @param packExts
|
457 |
+
* Set of {@link PackExt}s associated to this cache config.
|
458 |
+
* @param packExtCacheConfiguration
|
459 |
+
* {@link DfsBlockCacheConfig} for this cache config.
|
460 |
+
*/
|
461 |
+
DfsBlockCachePackExtConfig(EnumSet<PackExt> packExts,
|
462 |
+
DfsBlockCacheConfig packExtCacheConfiguration) {
|
463 |
+
this.packExts = packExts;
|
464 |
+
this.packExtCacheConfiguration = packExtCacheConfiguration;
|
465 |
+
}
|
466 |
+
|
467 |
+
Set<PackExt> getPackExts() {
|
468 |
+
return packExts;
|
469 |
+
}
|
470 |
+
|
471 |
+
DfsBlockCacheConfig getPackExtCacheConfiguration() {
|
472 |
+
return packExtCacheConfiguration;
|
473 |
+
}
|
474 |
+
|
475 |
+
private static DfsBlockCachePackExtConfig fromConfig(Config config,
|
476 |
+
String section, String subSection) {
|
477 |
+
String packExtensions = config.getString(section, subSection,
|
478 |
+
CONFIG_KEY_PACK_EXTENSIONS);
|
479 |
+
if (packExtensions == null) {
|
480 |
+
throw new IllegalArgumentException(
|
481 |
+
JGitText.get().noPackExtGivenForConfiguration);
|
482 |
+
}
|
483 |
+
String[] extensions = packExtensions.split(" ", -1); //$NON-NLS-1$
|
484 |
+
Set<PackExt> packExts = new HashSet<>(extensions.length);
|
485 |
+
for (String extension : extensions) {
|
486 |
+
try {
|
487 |
+
packExts.add(PackExt.valueOf(extension));
|
488 |
+
} catch (IllegalArgumentException e) {
|
489 |
+
throw new IllegalArgumentException(MessageFormat.format(
|
490 |
+
JGitText.get().unknownPackExtension, section,
|
491 |
+
subSection, CONFIG_KEY_PACK_EXTENSIONS, extension),
|
492 |
+
e);
|
493 |
+
}
|
494 |
+
}
|
495 |
+
|
496 |
+
DfsBlockCacheConfig dfsBlockCacheConfig = new DfsBlockCacheConfig();
|
497 |
+
dfsBlockCacheConfig.fromConfig(section, subSection, config);
|
498 |
+
return new DfsBlockCachePackExtConfig(EnumSet.copyOf(packExts),
|
499 |
+
dfsBlockCacheConfig);
|
500 |
+
}
|
501 |
+
}
|
502 |
}
|
@@ -129,18 +129,72 @@ <T> DfsBlockCache.Ref<T> getOrLoadRef(DfsStreamKey key, long position,
|
|
129 |
<T> T get(DfsStreamKey key, long position);
|
130 |
|
131 |
/**
|
132 |
-
* Get the
|
133 |
* statistics.
|
134 |
*
|
135 |
-
* @return the
|
136 |
* statistics.
|
137 |
*/
|
138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
|
140 |
/**
|
141 |
* Keeps track of stats for a Block Cache table.
|
142 |
*/
|
143 |
-
class DfsBlockCacheStats {
|
144 |
/**
|
145 |
* Number of times a block was found in the cache, per pack file
|
146 |
* extension.
|
@@ -214,44 +268,23 @@ void addToLiveBytes(DfsStreamKey key, long size) {
|
|
214 |
getStat(liveBytes, key).addAndGet(size);
|
215 |
}
|
216 |
|
217 |
-
|
218 |
-
|
219 |
-
*
|
220 |
-
* @return total number of bytes in the cache, per pack file extension.
|
221 |
-
*/
|
222 |
-
long[] getCurrentSize() {
|
223 |
return getStatVals(liveBytes);
|
224 |
}
|
225 |
|
226 |
-
|
227 |
-
|
228 |
-
* extension.
|
229 |
-
*
|
230 |
-
* @return the number of requests for items in the cache, per pack file
|
231 |
-
* extension.
|
232 |
-
*/
|
233 |
-
long[] getHitCount() {
|
234 |
return getStatVals(statHit);
|
235 |
}
|
236 |
|
237 |
-
|
238 |
-
|
239 |
-
* extension.
|
240 |
-
*
|
241 |
-
* @return the number of requests for items not in the cache, per pack
|
242 |
-
* file extension.
|
243 |
-
*/
|
244 |
-
long[] getMissCount() {
|
245 |
return getStatVals(statMiss);
|
246 |
}
|
247 |
|
248 |
-
|
249 |
-
|
250 |
-
*
|
251 |
-
* @return total number of requests (hit + miss), per pack file
|
252 |
-
* extension.
|
253 |
-
*/
|
254 |
-
long[] getTotalRequestCount() {
|
255 |
AtomicLong[] hit = statHit.get();
|
256 |
AtomicLong[] miss = statMiss.get();
|
257 |
long[] cnt = new long[Math.max(hit.length, miss.length)];
|
@@ -264,12 +297,8 @@ long[] getTotalRequestCount() {
|
|
264 |
return cnt;
|
265 |
}
|
266 |
|
267 |
-
|
268 |
-
|
269 |
-
*
|
270 |
-
* @return hit ratios.
|
271 |
-
*/
|
272 |
-
long[] getHitRatio() {
|
273 |
AtomicLong[] hit = statHit.get();
|
274 |
AtomicLong[] miss = statMiss.get();
|
275 |
long[] ratio = new long[Math.max(hit.length, miss.length)];
|
@@ -288,14 +317,8 @@ long[] getHitRatio() {
|
|
288 |
return ratio;
|
289 |
}
|
290 |
|
291 |
-
|
292 |
-
|
293 |
-
* file extension.
|
294 |
-
*
|
295 |
-
* @return the number of evictions performed due to cache being full,
|
296 |
-
* per pack file extension.
|
297 |
-
*/
|
298 |
-
long[] getEvictions() {
|
299 |
return getStatVals(statEvict);
|
300 |
}
|
301 |
|
|
|
129 |
<T> T get(DfsStreamKey key, long position);
|
130 |
|
131 |
/**
|
132 |
+
* Get the {@link BlockCacheStats} object for this block cache table's
|
133 |
* statistics.
|
134 |
*
|
135 |
+
* @return the {@link BlockCacheStats} tracking this block cache table's
|
136 |
* statistics.
|
137 |
*/
|
138 |
+
BlockCacheStats getBlockCacheStats();
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Provides methods used with Block Cache statistics.
|
142 |
+
*/
|
143 |
+
interface BlockCacheStats {
|
144 |
+
/**
|
145 |
+
* Get total number of bytes in the cache, per pack file extension.
|
146 |
+
*
|
147 |
+
* @return total number of bytes in the cache, per pack file extension.
|
148 |
+
*/
|
149 |
+
long[] getCurrentSize();
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Get number of requests for items in the cache, per pack file
|
153 |
+
* extension.
|
154 |
+
*
|
155 |
+
* @return the number of requests for items in the cache, per pack file
|
156 |
+
* extension.
|
157 |
+
*/
|
158 |
+
long[] getHitCount();
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Get number of requests for items not in the cache, per pack file
|
162 |
+
* extension.
|
163 |
+
*
|
164 |
+
* @return the number of requests for items not in the cache, per pack
|
165 |
+
* file extension.
|
166 |
+
*/
|
167 |
+
long[] getMissCount();
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Get total number of requests (hit + miss), per pack file extension.
|
171 |
+
*
|
172 |
+
* @return total number of requests (hit + miss), per pack file
|
173 |
+
* extension.
|
174 |
+
*/
|
175 |
+
long[] getTotalRequestCount();
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Get hit ratios.
|
179 |
+
*
|
180 |
+
* @return hit ratios.
|
181 |
+
*/
|
182 |
+
long[] getHitRatio();
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Get number of evictions performed due to cache being full, per pack
|
186 |
+
* file extension.
|
187 |
+
*
|
188 |
+
* @return the number of evictions performed due to cache being full,
|
189 |
+
* per pack file extension.
|
190 |
+
*/
|
191 |
+
long[] getEvictions();
|
192 |
+
}
|
193 |
|
194 |
/**
|
195 |
* Keeps track of stats for a Block Cache table.
|
196 |
*/
|
197 |
+
class DfsBlockCacheStats implements BlockCacheStats {
|
198 |
/**
|
199 |
* Number of times a block was found in the cache, per pack file
|
200 |
* extension.
|
|
|
268 |
getStat(liveBytes, key).addAndGet(size);
|
269 |
}
|
270 |
|
271 |
+
@Override
|
272 |
+
public long[] getCurrentSize() {
|
|
|
|
|
|
|
|
|
273 |
return getStatVals(liveBytes);
|
274 |
}
|
275 |
|
276 |
+
@Override
|
277 |
+
public long[] getHitCount() {
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
return getStatVals(statHit);
|
279 |
}
|
280 |
|
281 |
+
@Override
|
282 |
+
public long[] getMissCount() {
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
return getStatVals(statMiss);
|
284 |
}
|
285 |
|
286 |
+
@Override
|
287 |
+
public long[] getTotalRequestCount() {
|
|
|
|
|
|
|
|
|
|
|
288 |
AtomicLong[] hit = statHit.get();
|
289 |
AtomicLong[] miss = statMiss.get();
|
290 |
long[] cnt = new long[Math.max(hit.length, miss.length)];
|
|
|
297 |
return cnt;
|
298 |
}
|
299 |
|
300 |
+
@Override
|
301 |
+
public long[] getHitRatio() {
|
|
|
|
|
|
|
|
|
302 |
AtomicLong[] hit = statHit.get();
|
303 |
AtomicLong[] miss = statMiss.get();
|
304 |
long[] ratio = new long[Math.max(hit.length, miss.length)];
|
|
|
317 |
return ratio;
|
318 |
}
|
319 |
|
320 |
+
@Override
|
321 |
+
public long[] getEvictions() {
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
return getStatVals(statEvict);
|
323 |
}
|
324 |
|
@@ -29,6 +29,7 @@
|
|
29 |
import java.text.MessageFormat;
|
30 |
import java.util.Set;
|
31 |
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
32 |
import java.util.zip.CRC32;
|
33 |
import java.util.zip.DataFormatException;
|
34 |
import java.util.zip.Inflater;
|
@@ -106,6 +107,53 @@ public final class DfsPackFile extends BlockBasedFile {
|
|
106 |
/** Lock for {@link #corruptObjects}. */
|
107 |
private final Object corruptObjectsLock = new Object();
|
108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
/**
|
110 |
* Construct a reader for an existing, packfile.
|
111 |
*
|
@@ -115,7 +163,8 @@ public final class DfsPackFile extends BlockBasedFile {
|
|
115 |
* description of the pack within the DFS.
|
116 |
*/
|
117 |
DfsPackFile(DfsBlockCache cache, DfsPackDescription desc) {
|
118 |
-
this(cache, desc, DEFAULT_BITMAP_LOADER
|
|
|
119 |
}
|
120 |
|
121 |
/**
|
@@ -127,9 +176,11 @@ public final class DfsPackFile extends BlockBasedFile {
|
|
127 |
* description of the pack within the DFS
|
128 |
* @param bitmapLoader
|
129 |
* loader to get the bitmaps of this pack (if any)
|
|
|
|
|
130 |
*/
|
131 |
public DfsPackFile(DfsBlockCache cache, DfsPackDescription desc,
|
132 |
-
PackBitmapIndexLoader bitmapLoader) {
|
133 |
super(cache, desc, PACK);
|
134 |
|
135 |
int bs = desc.getBlockSize(PACK);
|
@@ -141,6 +192,7 @@ public DfsPackFile(DfsBlockCache cache, DfsPackDescription desc,
|
|
141 |
length = sz > 0 ? sz : -1;
|
142 |
|
143 |
this.bitmapLoader = bitmapLoader;
|
|
|
144 |
}
|
145 |
|
146 |
/**
|
@@ -195,19 +247,10 @@ private PackIndex idx(DfsReader ctx) throws IOException {
|
|
195 |
Repository.getGlobalListenerList()
|
196 |
.dispatch(new BeforeDfsPackIndexLoadedEvent(this));
|
197 |
try {
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
cacheHit.set(false);
|
203 |
-
return loadPackIndex(ctx, idxKey);
|
204 |
-
});
|
205 |
-
if (cacheHit.get()) {
|
206 |
-
ctx.stats.idxCacheHit++;
|
207 |
-
}
|
208 |
-
PackIndex idx = idxref.get();
|
209 |
-
if (index == null && idx != null) {
|
210 |
-
index = idx;
|
211 |
}
|
212 |
ctx.emitIndexLoad(desc, INDEX, index);
|
213 |
return index;
|
@@ -321,20 +364,10 @@ public PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
|
|
321 |
return reverseIndex;
|
322 |
}
|
323 |
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
REF_POSITION, () -> {
|
329 |
-
cacheHit.set(false);
|
330 |
-
return loadReverseIdx(ctx, revKey, idx);
|
331 |
-
});
|
332 |
-
if (cacheHit.get()) {
|
333 |
-
ctx.stats.ridxCacheHit++;
|
334 |
-
}
|
335 |
-
PackReverseIndex revidx = revref.get();
|
336 |
-
if (reverseIndex == null && revidx != null) {
|
337 |
-
reverseIndex = revidx;
|
338 |
}
|
339 |
ctx.emitIndexLoad(desc, REVERSE_INDEX, reverseIndex);
|
340 |
return reverseIndex;
|
@@ -347,6 +380,7 @@ private PackObjectSizeIndex getObjectSizeIndex(DfsReader ctx)
|
|
347 |
}
|
348 |
|
349 |
if (objectSizeIndexLoadAttempted
|
|
|
350 |
|| !desc.hasFileExt(OBJECT_SIZE_INDEX)) {
|
351 |
// Pack doesn't have object size index
|
352 |
return null;
|
@@ -1210,48 +1244,6 @@ private void setCorrupt(long offset) {
|
|
1210 |
}
|
1211 |
}
|
1212 |
|
1213 |
-
private DfsBlockCache.Ref<PackIndex> loadPackIndex(
|
1214 |
-
DfsReader ctx, DfsStreamKey idxKey) throws IOException {
|
1215 |
-
try {
|
1216 |
-
ctx.stats.readIdx++;
|
1217 |
-
long start = System.nanoTime();
|
1218 |
-
try (ReadableChannel rc = ctx.db.openFile(desc, INDEX)) {
|
1219 |
-
PackIndex idx = PackIndex.read(alignTo8kBlocks(rc));
|
1220 |
-
ctx.stats.readIdxBytes += rc.position();
|
1221 |
-
index = idx;
|
1222 |
-
return new DfsBlockCache.Ref<>(
|
1223 |
-
idxKey,
|
1224 |
-
REF_POSITION,
|
1225 |
-
idx.getObjectCount() * REC_SIZE,
|
1226 |
-
idx);
|
1227 |
-
} finally {
|
1228 |
-
ctx.stats.readIdxMicros += elapsedMicros(start);
|
1229 |
-
}
|
1230 |
-
} catch (EOFException e) {
|
1231 |
-
throw new IOException(MessageFormat.format(
|
1232 |
-
DfsText.get().shortReadOfIndex,
|
1233 |
-
desc.getFileName(INDEX)), e);
|
1234 |
-
} catch (IOException e) {
|
1235 |
-
throw new IOException(MessageFormat.format(
|
1236 |
-
DfsText.get().cannotReadIndex,
|
1237 |
-
desc.getFileName(INDEX)), e);
|
1238 |
-
}
|
1239 |
-
}
|
1240 |
-
|
1241 |
-
private DfsBlockCache.Ref<PackReverseIndex> loadReverseIdx(
|
1242 |
-
DfsReader ctx, DfsStreamKey revKey, PackIndex idx) {
|
1243 |
-
ctx.stats.readReverseIdx++;
|
1244 |
-
long start = System.nanoTime();
|
1245 |
-
PackReverseIndex revidx = PackReverseIndexFactory.computeFromIndex(idx);
|
1246 |
-
reverseIndex = revidx;
|
1247 |
-
ctx.stats.readReverseIdxMicros += elapsedMicros(start);
|
1248 |
-
return new DfsBlockCache.Ref<>(
|
1249 |
-
revKey,
|
1250 |
-
REF_POSITION,
|
1251 |
-
idx.getObjectCount() * 8,
|
1252 |
-
revidx);
|
1253 |
-
}
|
1254 |
-
|
1255 |
private DfsBlockCache.Ref<PackObjectSizeIndex> loadObjectSizeIndex(
|
1256 |
DfsReader ctx, DfsStreamKey objectSizeIndexKey) throws IOException {
|
1257 |
ctx.stats.readObjectSizeIndex++;
|
@@ -1288,9 +1280,12 @@ private DfsBlockCache.Ref<PackObjectSizeIndex> loadObjectSizeIndex(
|
|
1288 |
private DfsBlockCache.Ref<PackBitmapIndex> loadBitmapIndex(DfsReader ctx,
|
1289 |
DfsStreamKey bitmapKey) throws IOException {
|
1290 |
ctx.stats.readBitmap++;
|
|
|
1291 |
PackBitmapIndexLoader.LoadResult result = bitmapLoader
|
1292 |
.loadPackBitmapIndex(ctx, this);
|
1293 |
bitmapIndex = result.bitmapIndex;
|
|
|
|
|
1294 |
return new DfsBlockCache.Ref<>(bitmapKey, REF_POSITION,
|
1295 |
result.bytesRead, result.bitmapIndex);
|
1296 |
}
|
@@ -1449,4 +1444,141 @@ public LoadResult loadPackBitmapIndex(DfsReader ctx, DfsPackFile pack)
|
|
1449 |
}
|
1450 |
}
|
1451 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1452 |
}
|
|
|
29 |
import java.text.MessageFormat;
|
30 |
import java.util.Set;
|
31 |
import java.util.concurrent.atomic.AtomicBoolean;
|
32 |
+
import java.util.concurrent.atomic.AtomicReference;
|
33 |
import java.util.zip.CRC32;
|
34 |
import java.util.zip.DataFormatException;
|
35 |
import java.util.zip.Inflater;
|
|
|
107 |
/** Lock for {@link #corruptObjects}. */
|
108 |
private final Object corruptObjectsLock = new Object();
|
109 |
|
110 |
+
private final IndexFactory indexFactory;
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Returns the indexes for this pack.
|
114 |
+
* <p>
|
115 |
+
* We define indexes in different sub interfaces to allow implementing the
|
116 |
+
* indexes over different combinations of backends.
|
117 |
+
* <p>
|
118 |
+
* Implementations decide if/how to cache the indexes. The calling
|
119 |
+
* DfsPackFile will keep the reference to the index as long as it needs it.
|
120 |
+
*/
|
121 |
+
public interface IndexFactory {
|
122 |
+
/**
|
123 |
+
* Take care of loading the primary and reverse indexes for this pack.
|
124 |
+
*/
|
125 |
+
interface PackIndexes {
|
126 |
+
/**
|
127 |
+
* Load the primary index for the pack.
|
128 |
+
*
|
129 |
+
* @param ctx
|
130 |
+
* reader to find the raw bytes
|
131 |
+
* @return a primary index
|
132 |
+
* @throws IOException
|
133 |
+
* a problem finding/parsing the index
|
134 |
+
*/
|
135 |
+
PackIndex index(DfsReader ctx) throws IOException;
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Load the reverse index of the pack
|
139 |
+
*
|
140 |
+
* @param ctx
|
141 |
+
* reader to find the raw bytes
|
142 |
+
* @return the reverse index of the pack
|
143 |
+
* @throws IOException
|
144 |
+
* a problem finding/parsing the reverse index
|
145 |
+
*/
|
146 |
+
PackReverseIndex reverseIndex(DfsReader ctx) throws IOException;
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Returns a provider of the primary and reverse indexes of this pack
|
151 |
+
*
|
152 |
+
* @return an implementation of the {@link PackIndexes} interface
|
153 |
+
*/
|
154 |
+
PackIndexes getPackIndexes();
|
155 |
+
}
|
156 |
+
|
157 |
/**
|
158 |
* Construct a reader for an existing, packfile.
|
159 |
*
|
|
|
163 |
* description of the pack within the DFS.
|
164 |
*/
|
165 |
DfsPackFile(DfsBlockCache cache, DfsPackDescription desc) {
|
166 |
+
this(cache, desc, DEFAULT_BITMAP_LOADER,
|
167 |
+
new CachedStreamIndexFactory(cache, desc));
|
168 |
}
|
169 |
|
170 |
/**
|
|
|
176 |
* description of the pack within the DFS
|
177 |
* @param bitmapLoader
|
178 |
* loader to get the bitmaps of this pack (if any)
|
179 |
+
* @param indexFactory
|
180 |
+
* an IndexFactory to get references to the indexes of this pack
|
181 |
*/
|
182 |
public DfsPackFile(DfsBlockCache cache, DfsPackDescription desc,
|
183 |
+
PackBitmapIndexLoader bitmapLoader, IndexFactory indexFactory) {
|
184 |
super(cache, desc, PACK);
|
185 |
|
186 |
int bs = desc.getBlockSize(PACK);
|
|
|
192 |
length = sz > 0 ? sz : -1;
|
193 |
|
194 |
this.bitmapLoader = bitmapLoader;
|
195 |
+
this.indexFactory = indexFactory;
|
196 |
}
|
197 |
|
198 |
/**
|
|
|
247 |
Repository.getGlobalListenerList()
|
248 |
.dispatch(new BeforeDfsPackIndexLoadedEvent(this));
|
249 |
try {
|
250 |
+
index = indexFactory.getPackIndexes().index(ctx);
|
251 |
+
if (index == null) {
|
252 |
+
throw new IOException(
|
253 |
+
"Couldn't get a reference to the primary index"); //$NON-NLS-1$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
}
|
255 |
ctx.emitIndexLoad(desc, INDEX, index);
|
256 |
return index;
|
|
|
364 |
return reverseIndex;
|
365 |
}
|
366 |
|
367 |
+
reverseIndex = indexFactory.getPackIndexes().reverseIndex(ctx);
|
368 |
+
if (reverseIndex == null) {
|
369 |
+
throw new IOException(
|
370 |
+
"Couldn't get a reference to the reverse index"); //$NON-NLS-1$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
}
|
372 |
ctx.emitIndexLoad(desc, REVERSE_INDEX, reverseIndex);
|
373 |
return reverseIndex;
|
|
|
380 |
}
|
381 |
|
382 |
if (objectSizeIndexLoadAttempted
|
383 |
+
|| !ctx.getOptions().shouldUseObjectSizeIndex()
|
384 |
|| !desc.hasFileExt(OBJECT_SIZE_INDEX)) {
|
385 |
// Pack doesn't have object size index
|
386 |
return null;
|
|
|
1244 |
}
|
1245 |
}
|
1246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1247 |
private DfsBlockCache.Ref<PackObjectSizeIndex> loadObjectSizeIndex(
|
1248 |
DfsReader ctx, DfsStreamKey objectSizeIndexKey) throws IOException {
|
1249 |
ctx.stats.readObjectSizeIndex++;
|
|
|
1280 |
private DfsBlockCache.Ref<PackBitmapIndex> loadBitmapIndex(DfsReader ctx,
|
1281 |
DfsStreamKey bitmapKey) throws IOException {
|
1282 |
ctx.stats.readBitmap++;
|
1283 |
+
long start = System.nanoTime();
|
1284 |
PackBitmapIndexLoader.LoadResult result = bitmapLoader
|
1285 |
.loadPackBitmapIndex(ctx, this);
|
1286 |
bitmapIndex = result.bitmapIndex;
|
1287 |
+
ctx.stats.readBitmapIdxBytes += result.bytesRead;
|
1288 |
+
ctx.stats.readBitmapIdxMicros += elapsedMicros(start);
|
1289 |
return new DfsBlockCache.Ref<>(bitmapKey, REF_POSITION,
|
1290 |
result.bytesRead, result.bitmapIndex);
|
1291 |
}
|
|
|
1444 |
}
|
1445 |
}
|
1446 |
}
|
1447 |
+
|
1448 |
+
/**
|
1449 |
+
* An index factory backed by Dfs streams and references cached in
|
1450 |
+
* DfsBlockCache
|
1451 |
+
*/
|
1452 |
+
public static final class CachedStreamIndexFactory implements IndexFactory {
|
1453 |
+
private final CachedStreamPackIndexes indexes;
|
1454 |
+
|
1455 |
+
/**
|
1456 |
+
* An index factory
|
1457 |
+
*
|
1458 |
+
* @param cache
|
1459 |
+
* DFS block cache to use for the references
|
1460 |
+
* @param desc
|
1461 |
+
* This factory loads indexes for this package
|
1462 |
+
*/
|
1463 |
+
public CachedStreamIndexFactory(DfsBlockCache cache,
|
1464 |
+
DfsPackDescription desc) {
|
1465 |
+
this.indexes = new CachedStreamPackIndexes(cache, desc);
|
1466 |
+
}
|
1467 |
+
|
1468 |
+
@Override
|
1469 |
+
public PackIndexes getPackIndexes() {
|
1470 |
+
return indexes;
|
1471 |
+
}
|
1472 |
+
}
|
1473 |
+
|
1474 |
+
/**
|
1475 |
+
* Load primary and reverse index from Dfs streams and cache the references
|
1476 |
+
* in DfsBlockCache.
|
1477 |
+
*/
|
1478 |
+
public static final class CachedStreamPackIndexes implements IndexFactory.PackIndexes {
|
1479 |
+
private final DfsBlockCache cache;
|
1480 |
+
|
1481 |
+
private final DfsPackDescription desc;
|
1482 |
+
|
1483 |
+
/**
|
1484 |
+
* An index factory
|
1485 |
+
*
|
1486 |
+
* @param cache
|
1487 |
+
* DFS block cache to use for the references
|
1488 |
+
* @param desc This factory loads indexes for this package
|
1489 |
+
*/
|
1490 |
+
public CachedStreamPackIndexes(DfsBlockCache cache,
|
1491 |
+
DfsPackDescription desc) {
|
1492 |
+
this.cache = cache;
|
1493 |
+
this.desc = desc;
|
1494 |
+
}
|
1495 |
+
|
1496 |
+
@Override
|
1497 |
+
public PackIndex index(DfsReader ctx) throws IOException {
|
1498 |
+
DfsStreamKey idxKey = desc.getStreamKey(INDEX);
|
1499 |
+
// Keep the value parsed in the loader, in case the Ref<> is
|
1500 |
+
// nullified in ClockBlockCacheTable#reserveSpace
|
1501 |
+
// before we read its value.
|
1502 |
+
AtomicReference<PackIndex> loadedRef = new AtomicReference<>(null);
|
1503 |
+
DfsBlockCache.Ref<PackIndex> cachedRef = cache.getOrLoadRef(idxKey,
|
1504 |
+
REF_POSITION, () -> {
|
1505 |
+
RefWithSize<PackIndex> idx = loadPackIndex(ctx, desc);
|
1506 |
+
loadedRef.set(idx.ref);
|
1507 |
+
return new DfsBlockCache.Ref<>(idxKey, REF_POSITION,
|
1508 |
+
idx.size, idx.ref);
|
1509 |
+
});
|
1510 |
+
if (loadedRef.get() == null) {
|
1511 |
+
ctx.stats.idxCacheHit++;
|
1512 |
+
}
|
1513 |
+
return cachedRef.get() != null ? cachedRef.get() : loadedRef.get();
|
1514 |
+
}
|
1515 |
+
|
1516 |
+
private static RefWithSize<PackIndex> loadPackIndex(DfsReader ctx,
|
1517 |
+
DfsPackDescription desc) throws IOException {
|
1518 |
+
try {
|
1519 |
+
ctx.stats.readIdx++;
|
1520 |
+
long start = System.nanoTime();
|
1521 |
+
try (ReadableChannel rc = ctx.db.openFile(desc, INDEX)) {
|
1522 |
+
PackIndex idx = PackIndex.read(alignTo8kBlocks(rc));
|
1523 |
+
ctx.stats.readIdxBytes += rc.position();
|
1524 |
+
return new RefWithSize<>(idx,
|
1525 |
+
idx.getObjectCount() * REC_SIZE);
|
1526 |
+
} finally {
|
1527 |
+
ctx.stats.readIdxMicros += elapsedMicros(start);
|
1528 |
+
}
|
1529 |
+
} catch (EOFException e) {
|
1530 |
+
throw new IOException(
|
1531 |
+
MessageFormat.format(DfsText.get().shortReadOfIndex,
|
1532 |
+
desc.getFileName(INDEX)),
|
1533 |
+
e);
|
1534 |
+
} catch (IOException e) {
|
1535 |
+
throw new IOException(
|
1536 |
+
MessageFormat.format(DfsText.get().cannotReadIndex,
|
1537 |
+
desc.getFileName(INDEX)),
|
1538 |
+
e);
|
1539 |
+
}
|
1540 |
+
}
|
1541 |
+
|
1542 |
+
@Override
|
1543 |
+
public PackReverseIndex reverseIndex(DfsReader ctx) throws IOException {
|
1544 |
+
PackIndex idx = index(ctx);
|
1545 |
+
DfsStreamKey revKey = desc.getStreamKey(REVERSE_INDEX);
|
1546 |
+
// Keep the value parsed in the loader, in case the Ref<> is
|
1547 |
+
// nullified in ClockBlockCacheTable#reserveSpace
|
1548 |
+
// before we read its value.
|
1549 |
+
AtomicReference<PackReverseIndex> loadedRef = new AtomicReference<>(
|
1550 |
+
null);
|
1551 |
+
DfsBlockCache.Ref<PackReverseIndex> cachedRef = cache
|
1552 |
+
.getOrLoadRef(revKey, REF_POSITION, () -> {
|
1553 |
+
RefWithSize<PackReverseIndex> ridx = loadReverseIdx(ctx,
|
1554 |
+
idx);
|
1555 |
+
loadedRef.set(ridx.ref);
|
1556 |
+
return new DfsBlockCache.Ref<>(revKey, REF_POSITION,
|
1557 |
+
ridx.size, ridx.ref);
|
1558 |
+
});
|
1559 |
+
if (loadedRef.get() == null) {
|
1560 |
+
ctx.stats.ridxCacheHit++;
|
1561 |
+
}
|
1562 |
+
return cachedRef.get() != null ? cachedRef.get() : loadedRef.get();
|
1563 |
+
}
|
1564 |
+
|
1565 |
+
private static RefWithSize<PackReverseIndex> loadReverseIdx(
|
1566 |
+
DfsReader ctx, PackIndex idx) {
|
1567 |
+
ctx.stats.readReverseIdx++;
|
1568 |
+
long start = System.nanoTime();
|
1569 |
+
PackReverseIndex revidx = PackReverseIndexFactory
|
1570 |
+
.computeFromIndex(idx);
|
1571 |
+
ctx.stats.readReverseIdxMicros += elapsedMicros(start);
|
1572 |
+
return new RefWithSize<>(revidx, idx.getObjectCount() * 8);
|
1573 |
+
}
|
1574 |
+
}
|
1575 |
+
|
1576 |
+
private static final class RefWithSize<V> {
|
1577 |
+
final V ref;
|
1578 |
+
final long size;
|
1579 |
+
RefWithSize(V ref, long size) {
|
1580 |
+
this.ref = ref;
|
1581 |
+
this.size = size;
|
1582 |
+
}
|
1583 |
+
}
|
1584 |
}
|
@@ -40,12 +40,12 @@ public static class Accumulator {
|
|
40 |
/** Total number of complete pack indexes read into memory. */
|
41 |
long readIdx;
|
42 |
|
43 |
-
/** Total number of complete bitmap indexes read into memory. */
|
44 |
-
long readBitmap;
|
45 |
-
|
46 |
/** Total number of reverse indexes added into memory. */
|
47 |
long readReverseIdx;
|
48 |
|
|
|
|
|
|
|
49 |
/** Total number of complete commit graphs read into memory. */
|
50 |
long readCommitGraph;
|
51 |
|
@@ -55,6 +55,9 @@ public static class Accumulator {
|
|
55 |
/** Total number of bytes read from pack indexes. */
|
56 |
long readIdxBytes;
|
57 |
|
|
|
|
|
|
|
58 |
/** Total number of bytes read from commit graphs. */
|
59 |
long readCommitGraphBytes;
|
60 |
|
@@ -67,18 +70,15 @@ public static class Accumulator {
|
|
67 |
/** Total microseconds spent creating reverse indexes. */
|
68 |
long readReverseIdxMicros;
|
69 |
|
|
|
|
|
|
|
70 |
/** Total microseconds spent creating commit graphs. */
|
71 |
long readCommitGraphMicros;
|
72 |
|
73 |
/** Total microseconds spent creating object size indexes */
|
74 |
long readObjectSizeIndexMicros;
|
75 |
|
76 |
-
/** Total number of bytes read from bitmap indexes. */
|
77 |
-
long readBitmapIdxBytes;
|
78 |
-
|
79 |
-
/** Total microseconds spent reading bitmap indexes. */
|
80 |
-
long readBitmapIdxMicros;
|
81 |
-
|
82 |
/** Total number of block cache hits. */
|
83 |
long blockCacheHit;
|
84 |
|
@@ -195,21 +195,21 @@ public long getReadReverseIndexCount() {
|
|
195 |
}
|
196 |
|
197 |
/**
|
198 |
-
* Get total number of
|
199 |
*
|
200 |
-
* @return total number of
|
201 |
*/
|
202 |
-
public long
|
203 |
-
return stats.
|
204 |
}
|
205 |
|
206 |
/**
|
207 |
-
* Get total number of
|
208 |
*
|
209 |
-
* @return total number of
|
210 |
*/
|
211 |
-
public long
|
212 |
-
return stats.
|
213 |
}
|
214 |
|
215 |
/**
|
@@ -230,6 +230,15 @@ public long getReadIndexBytes() {
|
|
230 |
return stats.readIdxBytes;
|
231 |
}
|
232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
/**
|
234 |
* Get total number of bytes read from commit graphs.
|
235 |
*
|
@@ -239,6 +248,15 @@ public long getCommitGraphBytes() {
|
|
239 |
return stats.readCommitGraphBytes;
|
240 |
}
|
241 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
/**
|
243 |
* Get total microseconds spent reading pack indexes.
|
244 |
*
|
@@ -258,30 +276,30 @@ public long getReadReverseIndexMicros() {
|
|
258 |
}
|
259 |
|
260 |
/**
|
261 |
-
* Get total microseconds spent reading
|
262 |
*
|
263 |
-
* @return total microseconds spent reading
|
264 |
*/
|
265 |
-
public long
|
266 |
-
return stats.
|
267 |
}
|
268 |
|
269 |
/**
|
270 |
-
* Get total
|
271 |
*
|
272 |
-
* @return total
|
273 |
*/
|
274 |
-
public long
|
275 |
-
return stats.
|
276 |
}
|
277 |
|
278 |
/**
|
279 |
-
* Get total microseconds spent reading
|
280 |
*
|
281 |
-
* @return total microseconds spent reading
|
282 |
*/
|
283 |
-
public long
|
284 |
-
return stats.
|
285 |
}
|
286 |
|
287 |
/**
|
|
|
40 |
/** Total number of complete pack indexes read into memory. */
|
41 |
long readIdx;
|
42 |
|
|
|
|
|
|
|
43 |
/** Total number of reverse indexes added into memory. */
|
44 |
long readReverseIdx;
|
45 |
|
46 |
+
/** Total number of complete bitmap indexes read into memory. */
|
47 |
+
long readBitmap;
|
48 |
+
|
49 |
/** Total number of complete commit graphs read into memory. */
|
50 |
long readCommitGraph;
|
51 |
|
|
|
55 |
/** Total number of bytes read from pack indexes. */
|
56 |
long readIdxBytes;
|
57 |
|
58 |
+
/** Total number of bytes read from bitmap indexes. */
|
59 |
+
long readBitmapIdxBytes;
|
60 |
+
|
61 |
/** Total number of bytes read from commit graphs. */
|
62 |
long readCommitGraphBytes;
|
63 |
|
|
|
70 |
/** Total microseconds spent creating reverse indexes. */
|
71 |
long readReverseIdxMicros;
|
72 |
|
73 |
+
/** Total microseconds spent reading bitmap indexes. */
|
74 |
+
long readBitmapIdxMicros;
|
75 |
+
|
76 |
/** Total microseconds spent creating commit graphs. */
|
77 |
long readCommitGraphMicros;
|
78 |
|
79 |
/** Total microseconds spent creating object size indexes */
|
80 |
long readObjectSizeIndexMicros;
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
/** Total number of block cache hits. */
|
83 |
long blockCacheHit;
|
84 |
|
|
|
195 |
}
|
196 |
|
197 |
/**
|
198 |
+
* Get total number of complete bitmap indexes read into memory.
|
199 |
*
|
200 |
+
* @return total number of complete bitmap indexes read into memory.
|
201 |
*/
|
202 |
+
public long getReadBitmapIndexCount() {
|
203 |
+
return stats.readBitmap;
|
204 |
}
|
205 |
|
206 |
/**
|
207 |
+
* Get total number of times the commit graph read into memory.
|
208 |
*
|
209 |
+
* @return total number of commit graph read into memory.
|
210 |
*/
|
211 |
+
public long getReadCommitGraphCount() {
|
212 |
+
return stats.readCommitGraph;
|
213 |
}
|
214 |
|
215 |
/**
|
|
|
230 |
return stats.readIdxBytes;
|
231 |
}
|
232 |
|
233 |
+
/**
|
234 |
+
* Get total number of bytes read from bitmap indexes.
|
235 |
+
*
|
236 |
+
* @return total number of bytes read from bitmap indexes.
|
237 |
+
*/
|
238 |
+
public long getReadBitmapIndexBytes() {
|
239 |
+
return stats.readBitmapIdxBytes;
|
240 |
+
}
|
241 |
+
|
242 |
/**
|
243 |
* Get total number of bytes read from commit graphs.
|
244 |
*
|
|
|
248 |
return stats.readCommitGraphBytes;
|
249 |
}
|
250 |
|
251 |
+
/**
|
252 |
+
* Get total number of bytes read from object size indexes.
|
253 |
+
*
|
254 |
+
* @return total number of bytes read from object size indexes.
|
255 |
+
*/
|
256 |
+
public long getObjectSizeIndexBytes() {
|
257 |
+
return stats.readObjectSizeIndexBytes;
|
258 |
+
}
|
259 |
+
|
260 |
/**
|
261 |
* Get total microseconds spent reading pack indexes.
|
262 |
*
|
|
|
276 |
}
|
277 |
|
278 |
/**
|
279 |
+
* Get total microseconds spent reading bitmap indexes.
|
280 |
*
|
281 |
+
* @return total microseconds spent reading bitmap indexes.
|
282 |
*/
|
283 |
+
public long getReadBitmapIndexMicros() {
|
284 |
+
return stats.readBitmapIdxMicros;
|
285 |
}
|
286 |
|
287 |
/**
|
288 |
+
* Get total microseconds spent reading commit graphs.
|
289 |
*
|
290 |
+
* @return total microseconds spent reading commit graphs.
|
291 |
*/
|
292 |
+
public long getReadCommitGraphMicros() {
|
293 |
+
return stats.readCommitGraphMicros;
|
294 |
}
|
295 |
|
296 |
/**
|
297 |
+
* Get total microseconds spent reading object size indexes.
|
298 |
*
|
299 |
+
* @return total microseconds spent reading object size indexes.
|
300 |
*/
|
301 |
+
public long getReadObjectSizeIndexMicros() {
|
302 |
+
return stats.readObjectSizeIndexMicros;
|
303 |
}
|
304 |
|
305 |
/**
|
@@ -15,6 +15,7 @@
|
|
15 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_BASE_CACHE_LIMIT;
|
16 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_BUFFER;
|
17 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_FILE_THRESHOLD;
|
|
|
18 |
|
19 |
import org.eclipse.jgit.lib.Config;
|
20 |
import org.eclipse.jgit.storage.pack.PackConfig;
|
@@ -36,6 +37,8 @@ public class DfsReaderOptions {
|
|
36 |
|
37 |
private boolean loadRevIndexInParallel;
|
38 |
|
|
|
|
|
39 |
/**
|
40 |
* Create a default reader configuration.
|
41 |
*/
|
@@ -136,6 +139,28 @@ public DfsReaderOptions setLoadRevIndexInParallel(
|
|
136 |
return this;
|
137 |
}
|
138 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
/**
|
140 |
* Update properties by setting fields from the configuration.
|
141 |
* <p>
|
@@ -168,6 +193,10 @@ public DfsReaderOptions fromConfig(Config rc) {
|
|
168 |
CONFIG_DFS_SECTION,
|
169 |
CONFIG_KEY_STREAM_BUFFER,
|
170 |
getStreamPackBufferSize()));
|
|
|
|
|
|
|
|
|
171 |
return this;
|
172 |
}
|
173 |
}
|
|
|
15 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_BASE_CACHE_LIMIT;
|
16 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_BUFFER;
|
17 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_FILE_THRESHOLD;
|
18 |
+
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_USE_OBJECT_SIZE_INDEX;
|
19 |
|
20 |
import org.eclipse.jgit.lib.Config;
|
21 |
import org.eclipse.jgit.storage.pack.PackConfig;
|
|
|
37 |
|
38 |
private boolean loadRevIndexInParallel;
|
39 |
|
40 |
+
private boolean useObjectSizeIndex;
|
41 |
+
|
42 |
/**
|
43 |
* Create a default reader configuration.
|
44 |
*/
|
|
|
139 |
return this;
|
140 |
}
|
141 |
|
142 |
+
/**
|
143 |
+
* Use the object size index if available.
|
144 |
+
*
|
145 |
+
* @return true if the reader should try to use the object size index. if
|
146 |
+
* false, the reader ignores that index.
|
147 |
+
*/
|
148 |
+
public boolean shouldUseObjectSizeIndex() {
|
149 |
+
return useObjectSizeIndex;
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Set if the reader should try to use the object size index
|
154 |
+
*
|
155 |
+
* @param useObjectSizeIndex true to use it, false to ignore the object size index
|
156 |
+
*
|
157 |
+
* @return {@code this}
|
158 |
+
*/
|
159 |
+
public DfsReaderOptions setUseObjectSizeIndex(boolean useObjectSizeIndex) {
|
160 |
+
this.useObjectSizeIndex = useObjectSizeIndex;
|
161 |
+
return this;
|
162 |
+
}
|
163 |
+
|
164 |
/**
|
165 |
* Update properties by setting fields from the configuration.
|
166 |
* <p>
|
|
|
193 |
CONFIG_DFS_SECTION,
|
194 |
CONFIG_KEY_STREAM_BUFFER,
|
195 |
getStreamPackBufferSize()));
|
196 |
+
|
197 |
+
setUseObjectSizeIndex(rc.getBoolean(CONFIG_CORE_SECTION,
|
198 |
+
CONFIG_DFS_SECTION, CONFIG_KEY_USE_OBJECT_SIZE_INDEX,
|
199 |
+
false));
|
200 |
return this;
|
201 |
}
|
202 |
}
|
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (c) 2024, Google LLC and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* http://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
|
11 |
+
package org.eclipse.jgit.internal.storage.dfs;
|
12 |
+
|
13 |
+
import java.io.IOException;
|
14 |
+
import java.text.MessageFormat;
|
15 |
+
import java.util.HashMap;
|
16 |
+
import java.util.HashSet;
|
17 |
+
import java.util.List;
|
18 |
+
import java.util.Map;
|
19 |
+
import java.util.Set;
|
20 |
+
import java.util.stream.Collectors;
|
21 |
+
|
22 |
+
import org.eclipse.jgit.internal.JGitText;
|
23 |
+
import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.ReadableChannelSupplier;
|
24 |
+
import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.Ref;
|
25 |
+
import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.RefLoader;
|
26 |
+
import org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheConfig.DfsBlockCachePackExtConfig;
|
27 |
+
import org.eclipse.jgit.internal.storage.pack.PackExt;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* A table that holds multiple cache tables accessed by {@link PackExt} types.
|
31 |
+
*
|
32 |
+
* <p>
|
33 |
+
* Allows the separation of entries from different {@link PackExt} types to
|
34 |
+
* limit churn in cache caused by entries of differing sizes.
|
35 |
+
* <p>
|
36 |
+
* Separating these tables enables the fine-tuning of cache tables per extension
|
37 |
+
* type.
|
38 |
+
*/
|
39 |
+
class PackExtBlockCacheTable implements DfsBlockCacheTable {
|
40 |
+
private final DfsBlockCacheTable defaultBlockCacheTable;
|
41 |
+
|
42 |
+
// Holds the unique tables backing the extBlockCacheTables values.
|
43 |
+
private final List<DfsBlockCacheTable> blockCacheTableList;
|
44 |
+
|
45 |
+
// Holds the mapping of PackExt to DfsBlockCacheTables.
|
46 |
+
// The relation between the size of extBlockCacheTables entries and
|
47 |
+
// blockCacheTableList entries is:
|
48 |
+
// blockCacheTableList.size() <= extBlockCacheTables.size()
|
49 |
+
private final Map<PackExt, DfsBlockCacheTable> extBlockCacheTables;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Builds the PackExtBlockCacheTable from a list of
|
53 |
+
* {@link DfsBlockCachePackExtConfig}s.
|
54 |
+
*
|
55 |
+
* @param cacheConfig
|
56 |
+
* {@link DfsBlockCacheConfig} containing
|
57 |
+
* {@link DfsBlockCachePackExtConfig}s used to configure
|
58 |
+
* PackExtBlockCacheTable. The {@link DfsBlockCacheConfig} holds
|
59 |
+
* the configuration for the default cache table.
|
60 |
+
* @return the cache table built from the given configs.
|
61 |
+
* @throws IllegalArgumentException
|
62 |
+
* when no {@link DfsBlockCachePackExtConfig} exists in the
|
63 |
+
* {@link DfsBlockCacheConfig}.
|
64 |
+
*/
|
65 |
+
static PackExtBlockCacheTable fromBlockCacheConfigs(
|
66 |
+
DfsBlockCacheConfig cacheConfig) {
|
67 |
+
DfsBlockCacheTable defaultTable = new ClockBlockCacheTable(cacheConfig);
|
68 |
+
Map<PackExt, DfsBlockCacheTable> packExtBlockCacheTables = new HashMap<>();
|
69 |
+
List<DfsBlockCachePackExtConfig> packExtConfigs = cacheConfig
|
70 |
+
.getPackExtCacheConfigurations();
|
71 |
+
if (packExtConfigs == null || packExtConfigs.size() == 0) {
|
72 |
+
throw new IllegalArgumentException(
|
73 |
+
JGitText.get().noPackExtConfigurationGiven);
|
74 |
+
}
|
75 |
+
for (DfsBlockCachePackExtConfig packExtCacheConfig : packExtConfigs) {
|
76 |
+
DfsBlockCacheTable table = new ClockBlockCacheTable(
|
77 |
+
packExtCacheConfig.getPackExtCacheConfiguration());
|
78 |
+
for (PackExt packExt : packExtCacheConfig.getPackExts()) {
|
79 |
+
if (packExtBlockCacheTables.containsKey(packExt)) {
|
80 |
+
throw new IllegalArgumentException(MessageFormat.format(
|
81 |
+
JGitText.get().duplicatePackExtensionsForCacheTables,
|
82 |
+
packExt));
|
83 |
+
}
|
84 |
+
packExtBlockCacheTables.put(packExt, table);
|
85 |
+
}
|
86 |
+
}
|
87 |
+
return fromCacheTables(defaultTable, packExtBlockCacheTables);
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Creates a new PackExtBlockCacheTable from the combination of a default
|
92 |
+
* {@link DfsBlockCacheTable} and a map of {@link PackExt}s to
|
93 |
+
* {@link DfsBlockCacheTable}s.
|
94 |
+
* <p>
|
95 |
+
* This method allows for the PackExtBlockCacheTable to handle a mapping of
|
96 |
+
* {@link PackExt}s to arbitrarily defined {@link DfsBlockCacheTable}
|
97 |
+
* implementations. This is especially useful for users wishing to implement
|
98 |
+
* custom cache tables.
|
99 |
+
* <p>
|
100 |
+
* This is currently made visible for testing.
|
101 |
+
*
|
102 |
+
* @param defaultBlockCacheTable
|
103 |
+
* the default table used when a handling a {@link PackExt} type
|
104 |
+
* that does not map to a {@link DfsBlockCacheTable} mapped by
|
105 |
+
* packExtsCacheTablePairs.
|
106 |
+
* @param packExtBlockCacheTables
|
107 |
+
* the mapping of {@link PackExt}s to
|
108 |
+
* {@link DfsBlockCacheTable}s. A single
|
109 |
+
* {@link DfsBlockCacheTable} can be defined for multiple
|
110 |
+
* {@link PackExt}s in a many-to-one relationship.
|
111 |
+
* @return the PackExtBlockCacheTable created from the
|
112 |
+
* defaultBlockCacheTable and packExtsCacheTablePairs mapping.
|
113 |
+
* @throws IllegalArgumentException
|
114 |
+
* when a {@link PackExt} is defined for multiple
|
115 |
+
* {@link DfsBlockCacheTable}s.
|
116 |
+
*/
|
117 |
+
static PackExtBlockCacheTable fromCacheTables(
|
118 |
+
DfsBlockCacheTable defaultBlockCacheTable,
|
119 |
+
Map<PackExt, DfsBlockCacheTable> packExtBlockCacheTables) {
|
120 |
+
Set<DfsBlockCacheTable> blockCacheTables = new HashSet<>();
|
121 |
+
blockCacheTables.add(defaultBlockCacheTable);
|
122 |
+
blockCacheTables.addAll(packExtBlockCacheTables.values());
|
123 |
+
return new PackExtBlockCacheTable(defaultBlockCacheTable,
|
124 |
+
List.copyOf(blockCacheTables), packExtBlockCacheTables);
|
125 |
+
}
|
126 |
+
|
127 |
+
private PackExtBlockCacheTable(DfsBlockCacheTable defaultBlockCacheTable,
|
128 |
+
List<DfsBlockCacheTable> blockCacheTableList,
|
129 |
+
Map<PackExt, DfsBlockCacheTable> extBlockCacheTables) {
|
130 |
+
this.defaultBlockCacheTable = defaultBlockCacheTable;
|
131 |
+
this.blockCacheTableList = blockCacheTableList;
|
132 |
+
this.extBlockCacheTables = extBlockCacheTables;
|
133 |
+
}
|
134 |
+
|
135 |
+
@Override
|
136 |
+
public boolean hasBlock0(DfsStreamKey key) {
|
137 |
+
return getTable(key).hasBlock0(key);
|
138 |
+
}
|
139 |
+
|
140 |
+
@Override
|
141 |
+
public DfsBlock getOrLoad(BlockBasedFile file, long position,
|
142 |
+
DfsReader dfsReader, ReadableChannelSupplier fileChannel)
|
143 |
+
throws IOException {
|
144 |
+
return getTable(file.ext).getOrLoad(file, position, dfsReader,
|
145 |
+
fileChannel);
|
146 |
+
}
|
147 |
+
|
148 |
+
@Override
|
149 |
+
public <T> Ref<T> getOrLoadRef(DfsStreamKey key, long position,
|
150 |
+
RefLoader<T> loader) throws IOException {
|
151 |
+
return getTable(key).getOrLoadRef(key, position, loader);
|
152 |
+
}
|
153 |
+
|
154 |
+
@Override
|
155 |
+
public void put(DfsBlock v) {
|
156 |
+
getTable(v.stream).put(v);
|
157 |
+
}
|
158 |
+
|
159 |
+
@Override
|
160 |
+
public <T> Ref<T> put(DfsStreamKey key, long pos, long size, T v) {
|
161 |
+
return getTable(key).put(key, pos, size, v);
|
162 |
+
}
|
163 |
+
|
164 |
+
@Override
|
165 |
+
public <T> Ref<T> putRef(DfsStreamKey key, long size, T v) {
|
166 |
+
return getTable(key).putRef(key, size, v);
|
167 |
+
}
|
168 |
+
|
169 |
+
@Override
|
170 |
+
public boolean contains(DfsStreamKey key, long position) {
|
171 |
+
return getTable(key).contains(key, position);
|
172 |
+
}
|
173 |
+
|
174 |
+
@Override
|
175 |
+
public <T> T get(DfsStreamKey key, long position) {
|
176 |
+
return getTable(key).get(key, position);
|
177 |
+
}
|
178 |
+
|
179 |
+
@Override
|
180 |
+
public BlockCacheStats getBlockCacheStats() {
|
181 |
+
return new CacheStats(blockCacheTableList.stream()
|
182 |
+
.map(DfsBlockCacheTable::getBlockCacheStats)
|
183 |
+
.collect(Collectors.toList()));
|
184 |
+
}
|
185 |
+
|
186 |
+
private DfsBlockCacheTable getTable(PackExt packExt) {
|
187 |
+
return extBlockCacheTables.getOrDefault(packExt,
|
188 |
+
defaultBlockCacheTable);
|
189 |
+
}
|
190 |
+
|
191 |
+
private DfsBlockCacheTable getTable(DfsStreamKey key) {
|
192 |
+
return extBlockCacheTables.getOrDefault(getPackExt(key),
|
193 |
+
defaultBlockCacheTable);
|
194 |
+
}
|
195 |
+
|
196 |
+
private static PackExt getPackExt(DfsStreamKey key) {
|
197 |
+
return PackExt.values()[key.packExtPos];
|
198 |
+
}
|
199 |
+
|
200 |
+
private static class CacheStats implements BlockCacheStats {
|
201 |
+
private final List<BlockCacheStats> blockCacheStats;
|
202 |
+
|
203 |
+
private CacheStats(List<BlockCacheStats> blockCacheStats) {
|
204 |
+
this.blockCacheStats = blockCacheStats;
|
205 |
+
}
|
206 |
+
|
207 |
+
@Override
|
208 |
+
public long[] getCurrentSize() {
|
209 |
+
long[] sums = emptyPackStats();
|
210 |
+
for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
|
211 |
+
sums = add(sums, blockCacheStatsEntry.getCurrentSize());
|
212 |
+
}
|
213 |
+
return sums;
|
214 |
+
}
|
215 |
+
|
216 |
+
@Override
|
217 |
+
public long[] getHitCount() {
|
218 |
+
long[] sums = emptyPackStats();
|
219 |
+
for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
|
220 |
+
sums = add(sums, blockCacheStatsEntry.getHitCount());
|
221 |
+
}
|
222 |
+
return sums;
|
223 |
+
}
|
224 |
+
|
225 |
+
@Override
|
226 |
+
public long[] getMissCount() {
|
227 |
+
long[] sums = emptyPackStats();
|
228 |
+
for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
|
229 |
+
sums = add(sums, blockCacheStatsEntry.getMissCount());
|
230 |
+
}
|
231 |
+
return sums;
|
232 |
+
}
|
233 |
+
|
234 |
+
@Override
|
235 |
+
public long[] getTotalRequestCount() {
|
236 |
+
long[] sums = emptyPackStats();
|
237 |
+
for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
|
238 |
+
sums = add(sums, blockCacheStatsEntry.getTotalRequestCount());
|
239 |
+
}
|
240 |
+
return sums;
|
241 |
+
}
|
242 |
+
|
243 |
+
@Override
|
244 |
+
public long[] getHitRatio() {
|
245 |
+
long[] hit = getHitCount();
|
246 |
+
long[] miss = getMissCount();
|
247 |
+
long[] ratio = new long[Math.max(hit.length, miss.length)];
|
248 |
+
for (int i = 0; i < ratio.length; i++) {
|
249 |
+
if (i >= hit.length) {
|
250 |
+
ratio[i] = 0;
|
251 |
+
} else if (i >= miss.length) {
|
252 |
+
ratio[i] = 100;
|
253 |
+
} else {
|
254 |
+
long total = hit[i] + miss[i];
|
255 |
+
ratio[i] = total == 0 ? 0 : hit[i] * 100 / total;
|
256 |
+
}
|
257 |
+
}
|
258 |
+
return ratio;
|
259 |
+
}
|
260 |
+
|
261 |
+
@Override
|
262 |
+
public long[] getEvictions() {
|
263 |
+
long[] sums = emptyPackStats();
|
264 |
+
for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
|
265 |
+
sums = add(sums, blockCacheStatsEntry.getEvictions());
|
266 |
+
}
|
267 |
+
return sums;
|
268 |
+
}
|
269 |
+
|
270 |
+
private static long[] emptyPackStats() {
|
271 |
+
return new long[PackExt.values().length];
|
272 |
+
}
|
273 |
+
|
274 |
+
private static long[] add(long[] first, long[] second) {
|
275 |
+
long[] sums = new long[Integer.max(first.length, second.length)];
|
276 |
+
int i;
|
277 |
+
for (i = 0; i < Integer.min(first.length, second.length); i++) {
|
278 |
+
sums[i] = first[i] + second[i];
|
279 |
+
}
|
280 |
+
for (int j = i; j < first.length; j++) {
|
281 |
+
sums[j] = first[i];
|
282 |
+
}
|
283 |
+
for (int j = i; j < second.length; j++) {
|
284 |
+
sums[j] = second[i];
|
285 |
+
}
|
286 |
+
return sums;
|
287 |
+
}
|
288 |
+
}
|
289 |
+
}
|
@@ -68,14 +68,14 @@ public class FileReftableDatabase extends RefDatabase {
|
|
68 |
private final FileReftableStack reftableStack;
|
69 |
|
70 |
FileReftableDatabase(FileRepository repo) throws IOException {
|
71 |
-
this(repo, new File(new File(repo.
|
72 |
Constants.TABLES_LIST));
|
73 |
}
|
74 |
|
75 |
FileReftableDatabase(FileRepository repo, File refstackName) throws IOException {
|
76 |
this.fileRepository = repo;
|
77 |
this.reftableStack = new FileReftableStack(refstackName,
|
78 |
-
|
79 |
() -> fileRepository.fireEvent(new RefsChangedEvent()),
|
80 |
() -> fileRepository.getConfig());
|
81 |
this.reftableDatabase = new ReftableDatabase() {
|
@@ -318,7 +318,7 @@ public void close() {
|
|
318 |
@Override
|
319 |
public void create() throws IOException {
|
320 |
FileUtils.mkdir(
|
321 |
-
new File(fileRepository.
|
322 |
true);
|
323 |
}
|
324 |
|
@@ -615,7 +615,7 @@ public static FileReftableDatabase convertFrom(FileRepository repo,
|
|
615 |
FileReftableDatabase newDb = null;
|
616 |
File reftableList = null;
|
617 |
try {
|
618 |
-
File reftableDir = new File(repo.
|
619 |
Constants.REFTABLE);
|
620 |
reftableList = new File(reftableDir, Constants.TABLES_LIST);
|
621 |
if (!reftableDir.isDirectory()) {
|
|
|
68 |
private final FileReftableStack reftableStack;
|
69 |
|
70 |
FileReftableDatabase(FileRepository repo) throws IOException {
|
71 |
+
this(repo, new File(new File(repo.getCommonDirectory(), Constants.REFTABLE),
|
72 |
Constants.TABLES_LIST));
|
73 |
}
|
74 |
|
75 |
FileReftableDatabase(FileRepository repo, File refstackName) throws IOException {
|
76 |
this.fileRepository = repo;
|
77 |
this.reftableStack = new FileReftableStack(refstackName,
|
78 |
+
new File(fileRepository.getCommonDirectory(), Constants.REFTABLE),
|
79 |
() -> fileRepository.fireEvent(new RefsChangedEvent()),
|
80 |
() -> fileRepository.getConfig());
|
81 |
this.reftableDatabase = new ReftableDatabase() {
|
|
|
318 |
@Override
|
319 |
public void create() throws IOException {
|
320 |
FileUtils.mkdir(
|
321 |
+
new File(fileRepository.getCommonDirectory(), Constants.REFTABLE),
|
322 |
true);
|
323 |
}
|
324 |
|
|
|
615 |
FileReftableDatabase newDb = null;
|
616 |
File reftableList = null;
|
617 |
try {
|
618 |
+
File reftableDir = new File(repo.getCommonDirectory(),
|
619 |
Constants.REFTABLE);
|
620 |
reftableList = new File(reftableDir, Constants.TABLES_LIST);
|
621 |
if (!reftableDir.isDirectory()) {
|
@@ -165,7 +165,7 @@ public FileRepository(BaseRepositoryBuilder options) throws IOException {
|
|
165 |
throw new IOException(e.getMessage(), e);
|
166 |
}
|
167 |
repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
|
168 |
-
|
169 |
getFS());
|
170 |
loadRepoConfig();
|
171 |
|
@@ -193,7 +193,7 @@ public FileRepository(BaseRepositoryBuilder options) throws IOException {
|
|
193 |
options.getObjectDirectory(), //
|
194 |
options.getAlternateObjectDirectories(), //
|
195 |
getFS(), //
|
196 |
-
new File(
|
197 |
|
198 |
if (objectDatabase.exists()) {
|
199 |
if (repositoryFormatVersion > 1)
|
@@ -622,16 +622,17 @@ public void autoGC(ProgressMonitor monitor) {
|
|
622 |
* on IO problem
|
623 |
*/
|
624 |
void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
|
|
|
625 |
List<Ref> all = refs.getRefs();
|
626 |
-
File packedRefs = new File(
|
627 |
if (packedRefs.exists()) {
|
628 |
throw new IOException(MessageFormat.format(JGitText.get().fileAlreadyExists,
|
629 |
packedRefs.getName()));
|
630 |
}
|
631 |
|
632 |
-
File refsFile = new File(
|
633 |
File refsHeadsFile = new File(refsFile, "heads");//$NON-NLS-1$
|
634 |
-
File headFile = new File(
|
635 |
FileReftableDatabase oldDb = (FileReftableDatabase) refs;
|
636 |
|
637 |
// Remove the dummy files that ensure compatibility with older git
|
@@ -701,7 +702,7 @@ void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
|
|
701 |
}
|
702 |
|
703 |
if (!backup) {
|
704 |
-
File reftableDir = new File(
|
705 |
FileUtils.delete(reftableDir,
|
706 |
FileUtils.RECURSIVE | FileUtils.IGNORE_ERRORS);
|
707 |
}
|
@@ -730,8 +731,10 @@ void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
|
|
730 |
@SuppressWarnings("nls")
|
731 |
void convertToReftable(boolean writeLogs, boolean backup)
|
732 |
throws IOException {
|
733 |
-
File
|
734 |
-
File
|
|
|
|
|
735 |
if (reftableDir.exists() && FileUtils.hasFiles(reftableDir.toPath())) {
|
736 |
throw new IOException(JGitText.get().reftableDirExists);
|
737 |
}
|
@@ -739,28 +742,28 @@ void convertToReftable(boolean writeLogs, boolean backup)
|
|
739 |
// Ignore return value, as it is tied to temporary newRefs file.
|
740 |
FileReftableDatabase.convertFrom(this, writeLogs);
|
741 |
|
742 |
-
File refsFile = new File(
|
743 |
|
744 |
// non-atomic: remove old data.
|
745 |
-
File packedRefs = new File(
|
746 |
-
File logsDir = new File(
|
747 |
|
748 |
List<String> additional = getRefDatabase().getAdditionalRefs().stream()
|
749 |
.map(Ref::getName).collect(toList());
|
750 |
additional.add(Constants.HEAD);
|
751 |
if (backup) {
|
752 |
-
FileUtils.rename(refsFile, new File(
|
753 |
if (packedRefs.exists()) {
|
754 |
-
FileUtils.rename(packedRefs, new File(
|
755 |
Constants.PACKED_REFS + ".old"));
|
756 |
}
|
757 |
if (logsDir.exists()) {
|
758 |
FileUtils.rename(logsDir,
|
759 |
-
new File(
|
760 |
}
|
761 |
for (String r : additional) {
|
762 |
-
FileUtils.rename(new File(
|
763 |
-
|
764 |
}
|
765 |
} else {
|
766 |
FileUtils.delete(packedRefs, FileUtils.SKIP_MISSING);
|
@@ -770,7 +773,7 @@ void convertToReftable(boolean writeLogs, boolean backup)
|
|
770 |
FileUtils.delete(refsFile,
|
771 |
FileUtils.RECURSIVE | FileUtils.SKIP_MISSING);
|
772 |
for (String r : additional) {
|
773 |
-
new File(
|
774 |
}
|
775 |
}
|
776 |
|
@@ -784,7 +787,7 @@ void convertToReftable(boolean writeLogs, boolean backup)
|
|
784 |
|
785 |
// Some tools might write directly into .git/refs/heads/BRANCH. By
|
786 |
// putting a file here, this fails spectacularly.
|
787 |
-
FileUtils.createNewFile(new File(refsFile,
|
788 |
|
789 |
repoConfig.setString(ConfigConstants.CONFIG_EXTENSIONS_SECTION, null,
|
790 |
ConfigConstants.CONFIG_KEY_REF_STORAGE,
|
|
|
165 |
throw new IOException(e.getMessage(), e);
|
166 |
}
|
167 |
repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
|
168 |
+
getCommonDirectory(), Constants.CONFIG),
|
169 |
getFS());
|
170 |
loadRepoConfig();
|
171 |
|
|
|
193 |
options.getObjectDirectory(), //
|
194 |
options.getAlternateObjectDirectories(), //
|
195 |
getFS(), //
|
196 |
+
new File(getCommonDirectory(), Constants.SHALLOW));
|
197 |
|
198 |
if (objectDatabase.exists()) {
|
199 |
if (repositoryFormatVersion > 1)
|
|
|
622 |
* on IO problem
|
623 |
*/
|
624 |
void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
|
625 |
+
File commonDirectory = getCommonDirectory();
|
626 |
List<Ref> all = refs.getRefs();
|
627 |
+
File packedRefs = new File(commonDirectory, Constants.PACKED_REFS);
|
628 |
if (packedRefs.exists()) {
|
629 |
throw new IOException(MessageFormat.format(JGitText.get().fileAlreadyExists,
|
630 |
packedRefs.getName()));
|
631 |
}
|
632 |
|
633 |
+
File refsFile = new File(commonDirectory, "refs"); //$NON-NLS-1$
|
634 |
File refsHeadsFile = new File(refsFile, "heads");//$NON-NLS-1$
|
635 |
+
File headFile = new File(commonDirectory, Constants.HEAD);
|
636 |
FileReftableDatabase oldDb = (FileReftableDatabase) refs;
|
637 |
|
638 |
// Remove the dummy files that ensure compatibility with older git
|
|
|
702 |
}
|
703 |
|
704 |
if (!backup) {
|
705 |
+
File reftableDir = new File(commonDirectory, Constants.REFTABLE);
|
706 |
FileUtils.delete(reftableDir,
|
707 |
FileUtils.RECURSIVE | FileUtils.IGNORE_ERRORS);
|
708 |
}
|
|
|
731 |
@SuppressWarnings("nls")
|
732 |
void convertToReftable(boolean writeLogs, boolean backup)
|
733 |
throws IOException {
|
734 |
+
File commonDirectory = getCommonDirectory();
|
735 |
+
File directory = getDirectory();
|
736 |
+
File reftableDir = new File(commonDirectory, Constants.REFTABLE);
|
737 |
+
File headFile = new File(directory, Constants.HEAD);
|
738 |
if (reftableDir.exists() && FileUtils.hasFiles(reftableDir.toPath())) {
|
739 |
throw new IOException(JGitText.get().reftableDirExists);
|
740 |
}
|
|
|
742 |
// Ignore return value, as it is tied to temporary newRefs file.
|
743 |
FileReftableDatabase.convertFrom(this, writeLogs);
|
744 |
|
745 |
+
File refsFile = new File(commonDirectory, "refs");
|
746 |
|
747 |
// non-atomic: remove old data.
|
748 |
+
File packedRefs = new File(commonDirectory, Constants.PACKED_REFS);
|
749 |
+
File logsDir = new File(commonDirectory, Constants.LOGS);
|
750 |
|
751 |
List<String> additional = getRefDatabase().getAdditionalRefs().stream()
|
752 |
.map(Ref::getName).collect(toList());
|
753 |
additional.add(Constants.HEAD);
|
754 |
if (backup) {
|
755 |
+
FileUtils.rename(refsFile, new File(commonDirectory, "refs.old"));
|
756 |
if (packedRefs.exists()) {
|
757 |
+
FileUtils.rename(packedRefs, new File(commonDirectory,
|
758 |
Constants.PACKED_REFS + ".old"));
|
759 |
}
|
760 |
if (logsDir.exists()) {
|
761 |
FileUtils.rename(logsDir,
|
762 |
+
new File(commonDirectory, Constants.LOGS + ".old"));
|
763 |
}
|
764 |
for (String r : additional) {
|
765 |
+
FileUtils.rename(new File(commonDirectory, r),
|
766 |
+
new File(commonDirectory, r + ".old"));
|
767 |
}
|
768 |
} else {
|
769 |
FileUtils.delete(packedRefs, FileUtils.SKIP_MISSING);
|
|
|
773 |
FileUtils.delete(refsFile,
|
774 |
FileUtils.RECURSIVE | FileUtils.SKIP_MISSING);
|
775 |
for (String r : additional) {
|
776 |
+
new File(commonDirectory, r).delete();
|
777 |
}
|
778 |
}
|
779 |
|
|
|
787 |
|
788 |
// Some tools might write directly into .git/refs/heads/BRANCH. By
|
789 |
// putting a file here, this fails spectacularly.
|
790 |
+
FileUtils.createNewFile(new File(refsFile, Constants.HEADS));
|
791 |
|
792 |
repoConfig.setString(ConfigConstants.CONFIG_EXTENSIONS_SECTION, null,
|
793 |
ConfigConstants.CONFIG_KEY_REF_STORAGE,
|
@@ -125,29 +125,6 @@ private static Object getFileKey(BasicFileAttributes fileAttributes) {
|
|
125 |
return fileKey == null ? MISSING_FILEKEY : fileKey;
|
126 |
}
|
127 |
|
128 |
-
/**
|
129 |
-
* Record a snapshot for a file for which the last modification time is
|
130 |
-
* already known.
|
131 |
-
* <p>
|
132 |
-
* This method should be invoked before the file is accessed.
|
133 |
-
* <p>
|
134 |
-
* Note that this method cannot rely on measuring file timestamp resolution
|
135 |
-
* to avoid racy git issues caused by finite file timestamp resolution since
|
136 |
-
* it's unknown in which filesystem the file is located. Hence the worst
|
137 |
-
* case fallback for timestamp resolution is used.
|
138 |
-
*
|
139 |
-
* @param modified
|
140 |
-
* the last modification time of the file
|
141 |
-
* @return the snapshot.
|
142 |
-
* @deprecated use {@link #save(Instant)} instead.
|
143 |
-
*/
|
144 |
-
@Deprecated
|
145 |
-
public static FileSnapshot save(long modified) {
|
146 |
-
final Instant read = Instant.now();
|
147 |
-
return new FileSnapshot(read, Instant.ofEpochMilli(modified),
|
148 |
-
UNKNOWN_SIZE, FALLBACK_TIMESTAMP_RESOLUTION, MISSING_FILEKEY);
|
149 |
-
}
|
150 |
-
|
151 |
/**
|
152 |
* Record a snapshot for a file for which the last modification time is
|
153 |
* already known.
|
@@ -278,17 +255,6 @@ private FileSnapshot(Instant read, Instant modified, long size,
|
|
278 |
this.fileKey = fileKey;
|
279 |
}
|
280 |
|
281 |
-
/**
|
282 |
-
* Get time of last snapshot update
|
283 |
-
*
|
284 |
-
* @return time of last snapshot update
|
285 |
-
* @deprecated use {@link #lastModifiedInstant()} instead
|
286 |
-
*/
|
287 |
-
@Deprecated
|
288 |
-
public long lastModified() {
|
289 |
-
return lastModified.toEpochMilli();
|
290 |
-
}
|
291 |
-
|
292 |
/**
|
293 |
* Get time of last snapshot update
|
294 |
*
|
|
|
125 |
return fileKey == null ? MISSING_FILEKEY : fileKey;
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
/**
|
129 |
* Record a snapshot for a file for which the last modification time is
|
130 |
* already known.
|
|
|
255 |
this.fileKey = fileKey;
|
256 |
}
|
257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
/**
|
259 |
* Get time of last snapshot update
|
260 |
*
|
@@ -1047,7 +1047,7 @@ private static boolean isTag(Ref ref) {
|
|
1047 |
}
|
1048 |
|
1049 |
private void deleteEmptyRefsFolders() throws IOException {
|
1050 |
-
Path refs = repo.
|
1051 |
// Avoid deleting a folder that was created after the threshold so that concurrent
|
1052 |
// operations trying to create a reference are not impacted
|
1053 |
Instant threshold = Instant.now().minus(30, ChronoUnit.SECONDS);
|
|
|
1047 |
}
|
1048 |
|
1049 |
private void deleteEmptyRefsFolders() throws IOException {
|
1050 |
+
Path refs = repo.getCommonDirectory().toPath().resolve(Constants.R_REFS);
|
1051 |
// Avoid deleting a folder that was created after the threshold so that concurrent
|
1052 |
// operations trying to create a reference are not impacted
|
1053 |
Instant threshold = Instant.now().minus(30, ChronoUnit.SECONDS);
|
@@ -50,7 +50,7 @@ class GcLog {
|
|
50 |
*/
|
51 |
GcLog(FileRepository repo) {
|
52 |
this.repo = repo;
|
53 |
-
logFile = new File(repo.
|
54 |
lock = new LockFile(logFile);
|
55 |
}
|
56 |
|
|
|
50 |
*/
|
51 |
GcLog(FileRepository repo) {
|
52 |
this.repo = repo;
|
53 |
+
logFile = new File(repo.getCommonDirectory(), "gc.log"); //$NON-NLS-1$
|
54 |
lock = new LockFile(logFile);
|
55 |
}
|
56 |
|
@@ -46,7 +46,7 @@ public AttributesNode load() throws IOException {
|
|
46 |
|
47 |
FS fs = repository.getFS();
|
48 |
|
49 |
-
File attributes = fs.resolve(repository.
|
50 |
Constants.INFO_ATTRIBUTES);
|
51 |
FileRepository.AttributesNodeProviderImpl.loadRulesFromFile(r, attributes);
|
52 |
|
|
|
46 |
|
47 |
FS fs = repository.getFS();
|
48 |
|
49 |
+
File attributes = fs.resolve(repository.getCommonDirectory(),
|
50 |
Constants.INFO_ATTRIBUTES);
|
51 |
FileRepository.AttributesNodeProviderImpl.loadRulesFromFile(r, attributes);
|
52 |
|
@@ -24,6 +24,7 @@
|
|
24 |
import java.nio.channels.Channels;
|
25 |
import java.nio.channels.FileChannel;
|
26 |
import java.nio.file.Files;
|
|
|
27 |
import java.nio.file.StandardCopyOption;
|
28 |
import java.nio.file.attribute.FileTime;
|
29 |
import java.text.MessageFormat;
|
@@ -141,9 +142,8 @@ public boolean lock() throws IOException {
|
|
141 |
throw new IllegalStateException(
|
142 |
MessageFormat.format(JGitText.get().lockAlreadyHeld, ref));
|
143 |
}
|
144 |
-
FileUtils.mkdirs(lck.getParentFile(), true);
|
145 |
try {
|
146 |
-
token =
|
147 |
} catch (IOException e) {
|
148 |
LOG.error(JGitText.get().failedCreateLockFile, lck, e);
|
149 |
throw e;
|
@@ -160,6 +160,19 @@ public boolean lock() throws IOException {
|
|
160 |
return obtainedLock;
|
161 |
}
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
/**
|
164 |
* Try to establish the lock for appending.
|
165 |
*
|
@@ -511,17 +524,6 @@ private void saveStatInformation() {
|
|
511 |
}
|
512 |
}
|
513 |
|
514 |
-
/**
|
515 |
-
* Get the modification time of the output file when it was committed.
|
516 |
-
*
|
517 |
-
* @return modification time of the lock file right before we committed it.
|
518 |
-
* @deprecated use {@link #getCommitLastModifiedInstant()} instead
|
519 |
-
*/
|
520 |
-
@Deprecated
|
521 |
-
public long getCommitLastModified() {
|
522 |
-
return commitSnapshot.lastModified();
|
523 |
-
}
|
524 |
-
|
525 |
/**
|
526 |
* Get the modification time of the output file when it was committed.
|
527 |
*
|
|
|
24 |
import java.nio.channels.Channels;
|
25 |
import java.nio.channels.FileChannel;
|
26 |
import java.nio.file.Files;
|
27 |
+
import java.nio.file.NoSuchFileException;
|
28 |
import java.nio.file.StandardCopyOption;
|
29 |
import java.nio.file.attribute.FileTime;
|
30 |
import java.text.MessageFormat;
|
|
|
142 |
throw new IllegalStateException(
|
143 |
MessageFormat.format(JGitText.get().lockAlreadyHeld, ref));
|
144 |
}
|
|
|
145 |
try {
|
146 |
+
token = createLockFileWithRetry();
|
147 |
} catch (IOException e) {
|
148 |
LOG.error(JGitText.get().failedCreateLockFile, lck, e);
|
149 |
throw e;
|
|
|
160 |
return obtainedLock;
|
161 |
}
|
162 |
|
163 |
+
private FS.LockToken createLockFileWithRetry() throws IOException {
|
164 |
+
try {
|
165 |
+
return createLockFile();
|
166 |
+
} catch (NoSuchFileException e) {
|
167 |
+
return createLockFile();
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
private FS.LockToken createLockFile() throws IOException {
|
172 |
+
FileUtils.mkdirs(lck.getParentFile(), true);
|
173 |
+
return FS.DETECTED.createNewFileAtomic(lck);
|
174 |
+
}
|
175 |
+
|
176 |
/**
|
177 |
* Try to establish the lock for appending.
|
178 |
*
|
|
|
524 |
}
|
525 |
}
|
526 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
527 |
/**
|
528 |
* Get the modification time of the output file when it was committed.
|
529 |
*
|
@@ -12,7 +12,7 @@
|
|
12 |
import java.io.IOException;
|
13 |
import java.io.InputStream;
|
14 |
import java.io.UnsupportedEncodingException;
|
15 |
-
import java.
|
16 |
|
17 |
import org.eclipse.jgit.internal.JGitText;
|
18 |
import org.eclipse.jgit.util.NB;
|
@@ -35,7 +35,7 @@ class PackObjectSizeIndexV1 implements PackObjectSizeIndex {
|
|
35 |
|
36 |
private final UInt24Array positions24;
|
37 |
|
38 |
-
private final
|
39 |
|
40 |
/**
|
41 |
* Parallel array to concat(positions24, positions32) with the size of the
|
@@ -45,35 +45,37 @@ class PackObjectSizeIndexV1 implements PackObjectSizeIndex {
|
|
45 |
* doesn't fit in an int and |value|-1 is the position for the size in the
|
46 |
* size64 array e.g. a value of -1 is sizes64[0], -2 = sizes64[1], ...
|
47 |
*/
|
48 |
-
private final
|
49 |
|
50 |
-
private final
|
51 |
|
52 |
static PackObjectSizeIndex parse(InputStream in) throws IOException {
|
53 |
/** Header and version already out of the input */
|
54 |
-
|
55 |
-
|
56 |
-
int
|
|
|
57 |
if (objCount == 0) {
|
58 |
return new EmptyPackObjectSizeIndex(threshold);
|
59 |
}
|
60 |
-
return new PackObjectSizeIndexV1(
|
61 |
}
|
62 |
|
63 |
-
private PackObjectSizeIndexV1(
|
64 |
int objCount) throws IOException {
|
65 |
this.threshold = threshold;
|
66 |
UInt24Array pos24 = null;
|
67 |
-
|
68 |
|
|
|
69 |
byte positionEncoding;
|
70 |
-
while ((positionEncoding =
|
71 |
if (Byte.compareUnsigned(positionEncoding, BITS_24) == 0) {
|
72 |
-
int sz =
|
73 |
pos24 = new UInt24Array(stream.readNBytes(sz * 3));
|
74 |
} else if (Byte.compareUnsigned(positionEncoding, BITS_32) == 0) {
|
75 |
-
int sz =
|
76 |
-
pos32 =
|
77 |
} else {
|
78 |
throw new UnsupportedEncodingException(
|
79 |
String.format(JGitText.get().unknownPositionEncoding,
|
@@ -81,16 +83,16 @@ private PackObjectSizeIndexV1(IndexInputStreamReader stream, int threshold,
|
|
81 |
}
|
82 |
}
|
83 |
positions24 = pos24 != null ? pos24 : UInt24Array.EMPTY;
|
84 |
-
positions32 = pos32 != null ? pos32 :
|
85 |
|
86 |
-
sizes32 =
|
87 |
-
int c64sizes =
|
88 |
if (c64sizes == 0) {
|
89 |
-
sizes64 =
|
90 |
return;
|
91 |
}
|
92 |
-
sizes64 =
|
93 |
-
int c128sizes =
|
94 |
if (c128sizes != 0) {
|
95 |
// this MUST be 0 (we don't support 128 bits sizes yet)
|
96 |
throw new IOException(JGitText.get().unsupportedSizesObjSizeIndex);
|
@@ -102,8 +104,8 @@ public long getSize(int idxOffset) {
|
|
102 |
int pos = -1;
|
103 |
if (!positions24.isEmpty() && idxOffset <= positions24.getLastValue()) {
|
104 |
pos = positions24.binarySearch(idxOffset);
|
105 |
-
} else if (positions32.
|
106 |
-
int pos32 =
|
107 |
if (pos32 >= 0) {
|
108 |
pos = pos32 + positions24.size();
|
109 |
}
|
@@ -112,17 +114,17 @@ public long getSize(int idxOffset) {
|
|
112 |
return -1;
|
113 |
}
|
114 |
|
115 |
-
int objSize = sizes32
|
116 |
if (objSize < 0) {
|
117 |
int secondPos = Math.abs(objSize) - 1;
|
118 |
-
return sizes64
|
119 |
}
|
120 |
return objSize;
|
121 |
}
|
122 |
|
123 |
@Override
|
124 |
public long getObjectCount() {
|
125 |
-
return (long) positions24.size() + positions32.
|
126 |
}
|
127 |
|
128 |
@Override
|
@@ -131,69 +133,128 @@ public int getThreshold() {
|
|
131 |
}
|
132 |
|
133 |
/**
|
134 |
-
*
|
135 |
*/
|
136 |
-
private static class
|
|
|
137 |
|
138 |
-
private final
|
139 |
|
140 |
-
private final
|
141 |
|
142 |
-
|
143 |
-
this.in = in;
|
144 |
-
}
|
145 |
|
146 |
-
int
|
147 |
-
int
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
150 |
}
|
151 |
-
return
|
|
|
|
|
|
|
|
|
|
|
152 |
}
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
}
|
163 |
-
return
|
164 |
}
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
}
|
171 |
-
return
|
172 |
}
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
|
|
|
|
|
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
|
|
|
|
|
|
|
|
182 |
}
|
183 |
-
return
|
184 |
}
|
185 |
|
186 |
-
byte readByte() throws IOException {
|
187 |
int n = in.readNBytes(buffer, 0, 1);
|
188 |
if (n != 1) {
|
189 |
throw new IOException(JGitText.get().cannotReadByte);
|
190 |
}
|
191 |
return buffer[0];
|
192 |
}
|
193 |
-
|
194 |
-
byte[] readNBytes(int sz) throws IOException {
|
195 |
-
return in.readNBytes(sz);
|
196 |
-
}
|
197 |
}
|
198 |
|
199 |
private static class EmptyPackObjectSizeIndex
|
|
|
12 |
import java.io.IOException;
|
13 |
import java.io.InputStream;
|
14 |
import java.io.UnsupportedEncodingException;
|
15 |
+
import java.text.MessageFormat;
|
16 |
|
17 |
import org.eclipse.jgit.internal.JGitText;
|
18 |
import org.eclipse.jgit.util.NB;
|
|
|
35 |
|
36 |
private final UInt24Array positions24;
|
37 |
|
38 |
+
private final IntArray positions32;
|
39 |
|
40 |
/**
|
41 |
* Parallel array to concat(positions24, positions32) with the size of the
|
|
|
45 |
* doesn't fit in an int and |value|-1 is the position for the size in the
|
46 |
* size64 array e.g. a value of -1 is sizes64[0], -2 = sizes64[1], ...
|
47 |
*/
|
48 |
+
private final IntArray sizes32;
|
49 |
|
50 |
+
private final LongArray sizes64;
|
51 |
|
52 |
static PackObjectSizeIndex parse(InputStream in) throws IOException {
|
53 |
/** Header and version already out of the input */
|
54 |
+
byte[] buffer = new byte[8];
|
55 |
+
in.readNBytes(buffer, 0, 8);
|
56 |
+
int threshold = NB.decodeInt32(buffer, 0); // minSize
|
57 |
+
int objCount = NB.decodeInt32(buffer, 4);
|
58 |
if (objCount == 0) {
|
59 |
return new EmptyPackObjectSizeIndex(threshold);
|
60 |
}
|
61 |
+
return new PackObjectSizeIndexV1(in, threshold, objCount);
|
62 |
}
|
63 |
|
64 |
+
private PackObjectSizeIndexV1(InputStream stream, int threshold,
|
65 |
int objCount) throws IOException {
|
66 |
this.threshold = threshold;
|
67 |
UInt24Array pos24 = null;
|
68 |
+
IntArray pos32 = null;
|
69 |
|
70 |
+
StreamHelper helper = new StreamHelper();
|
71 |
byte positionEncoding;
|
72 |
+
while ((positionEncoding = helper.readByte(stream)) != 0) {
|
73 |
if (Byte.compareUnsigned(positionEncoding, BITS_24) == 0) {
|
74 |
+
int sz = helper.readInt(stream);
|
75 |
pos24 = new UInt24Array(stream.readNBytes(sz * 3));
|
76 |
} else if (Byte.compareUnsigned(positionEncoding, BITS_32) == 0) {
|
77 |
+
int sz = helper.readInt(stream);
|
78 |
+
pos32 = IntArray.from(stream, sz);
|
79 |
} else {
|
80 |
throw new UnsupportedEncodingException(
|
81 |
String.format(JGitText.get().unknownPositionEncoding,
|
|
|
83 |
}
|
84 |
}
|
85 |
positions24 = pos24 != null ? pos24 : UInt24Array.EMPTY;
|
86 |
+
positions32 = pos32 != null ? pos32 : IntArray.EMPTY;
|
87 |
|
88 |
+
sizes32 = IntArray.from(stream, objCount);
|
89 |
+
int c64sizes = helper.readInt(stream);
|
90 |
if (c64sizes == 0) {
|
91 |
+
sizes64 = LongArray.EMPTY;
|
92 |
return;
|
93 |
}
|
94 |
+
sizes64 = LongArray.from(stream, c64sizes);
|
95 |
+
int c128sizes = helper.readInt(stream);
|
96 |
if (c128sizes != 0) {
|
97 |
// this MUST be 0 (we don't support 128 bits sizes yet)
|
98 |
throw new IOException(JGitText.get().unsupportedSizesObjSizeIndex);
|
|
|
104 |
int pos = -1;
|
105 |
if (!positions24.isEmpty() && idxOffset <= positions24.getLastValue()) {
|
106 |
pos = positions24.binarySearch(idxOffset);
|
107 |
+
} else if (!positions32.empty() && idxOffset >= positions32.get(0)) {
|
108 |
+
int pos32 = positions32.binarySearch(idxOffset);
|
109 |
if (pos32 >= 0) {
|
110 |
pos = pos32 + positions24.size();
|
111 |
}
|
|
|
114 |
return -1;
|
115 |
}
|
116 |
|
117 |
+
int objSize = sizes32.get(pos);
|
118 |
if (objSize < 0) {
|
119 |
int secondPos = Math.abs(objSize) - 1;
|
120 |
+
return sizes64.get(secondPos);
|
121 |
}
|
122 |
return objSize;
|
123 |
}
|
124 |
|
125 |
@Override
|
126 |
public long getObjectCount() {
|
127 |
+
return (long) positions24.size() + positions32.size();
|
128 |
}
|
129 |
|
130 |
@Override
|
|
|
133 |
}
|
134 |
|
135 |
/**
|
136 |
+
* A byte[] that should be interpreted as an int[]
|
137 |
*/
|
138 |
+
private static class IntArray {
|
139 |
+
private static final IntArray EMPTY = new IntArray(new byte[0]);
|
140 |
|
141 |
+
private static final int INT_SIZE = 4;
|
142 |
|
143 |
+
private final byte[] data;
|
144 |
|
145 |
+
private final int size;
|
|
|
|
|
146 |
|
147 |
+
static IntArray from(InputStream in, int ints) throws IOException {
|
148 |
+
int expectedBytes = ints * INT_SIZE;
|
149 |
+
byte[] data = in.readNBytes(expectedBytes);
|
150 |
+
if (data.length < expectedBytes) {
|
151 |
+
throw new IOException(MessageFormat
|
152 |
+
.format(JGitText.get().unableToReadFullArray,
|
153 |
+
Integer.valueOf(ints)));
|
154 |
}
|
155 |
+
return new IntArray(data);
|
156 |
+
}
|
157 |
+
|
158 |
+
private IntArray(byte[] data) {
|
159 |
+
this.data = data;
|
160 |
+
size = data.length / INT_SIZE;
|
161 |
}
|
162 |
|
163 |
+
/**
|
164 |
+
* Returns position of element in array, -1 if not there
|
165 |
+
*
|
166 |
+
* @param needle
|
167 |
+
* element to look for
|
168 |
+
* @return position of the element in the array or -1 if not found
|
169 |
+
*/
|
170 |
+
int binarySearch(int needle) {
|
171 |
+
if (size == 0) {
|
172 |
+
return -1;
|
173 |
}
|
174 |
+
int high = size;
|
175 |
+
int low = 0;
|
176 |
+
do {
|
177 |
+
int mid = (low + high) >>> 1;
|
178 |
+
int cmp = Integer.compare(needle, get(mid));
|
179 |
+
if (cmp < 0)
|
180 |
+
high = mid;
|
181 |
+
else if (cmp == 0) {
|
182 |
+
return mid;
|
183 |
+
} else
|
184 |
+
low = mid + 1;
|
185 |
+
} while (low < high);
|
186 |
+
return -1;
|
187 |
+
}
|
188 |
|
189 |
+
int get(int position) {
|
190 |
+
if (position < 0 || position >= size) {
|
191 |
+
throw new IndexOutOfBoundsException(position);
|
192 |
}
|
193 |
+
return NB.decodeInt32(data, position * INT_SIZE);
|
194 |
}
|
195 |
|
196 |
+
boolean empty() {
|
197 |
+
return size == 0;
|
198 |
+
}
|
199 |
+
|
200 |
+
int size() {
|
201 |
+
return size;
|
202 |
+
}
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* A byte[] that should be interpreted as an long[]
|
207 |
+
*/
|
208 |
+
private static class LongArray {
|
209 |
+
private static final LongArray EMPTY = new LongArray(new byte[0]);
|
210 |
+
|
211 |
+
private static final int LONG_SIZE = 8; // bytes
|
212 |
+
|
213 |
+
private final byte[] data;
|
214 |
+
|
215 |
+
private final int size;
|
216 |
+
|
217 |
+
static LongArray from(InputStream in, int longs) throws IOException {
|
218 |
+
byte[] data = in.readNBytes(longs * LONG_SIZE);
|
219 |
+
if (data.length < longs * LONG_SIZE) {
|
220 |
+
throw new IOException(MessageFormat
|
221 |
+
.format(JGitText.get().unableToReadFullArray,
|
222 |
+
Integer.valueOf(longs)));
|
223 |
}
|
224 |
+
return new LongArray(data);
|
225 |
}
|
226 |
|
227 |
+
private LongArray(byte[] data) {
|
228 |
+
this.data = data;
|
229 |
+
size = data.length / LONG_SIZE;
|
230 |
+
}
|
231 |
+
|
232 |
+
long get(int position) {
|
233 |
+
if (position < 0 || position >= size) {
|
234 |
+
throw new IndexOutOfBoundsException(position);
|
235 |
}
|
236 |
+
return NB.decodeInt64(data, position * LONG_SIZE);
|
237 |
+
}
|
238 |
+
}
|
239 |
|
240 |
+
private static class StreamHelper {
|
241 |
+
private final byte[] buffer = new byte[8];
|
242 |
+
|
243 |
+
int readInt(InputStream in) throws IOException {
|
244 |
+
int n = in.readNBytes(buffer, 0, 4);
|
245 |
+
if (n < 4) {
|
246 |
+
throw new IOException(JGitText.get().unableToReadFullInt);
|
247 |
}
|
248 |
+
return NB.decodeInt32(buffer, 0);
|
249 |
}
|
250 |
|
251 |
+
byte readByte(InputStream in) throws IOException {
|
252 |
int n = in.readNBytes(buffer, 0, 1);
|
253 |
if (n != 1) {
|
254 |
throw new IOException(JGitText.get().cannotReadByte);
|
255 |
}
|
256 |
return buffer[0];
|
257 |
}
|
|
|
|
|
|
|
|
|
258 |
}
|
259 |
|
260 |
private static class EmptyPackObjectSizeIndex
|
@@ -16,6 +16,7 @@
|
|
16 |
import static java.nio.charset.StandardCharsets.UTF_8;
|
17 |
import static org.eclipse.jgit.lib.Constants.HEAD;
|
18 |
import static org.eclipse.jgit.lib.Constants.LOGS;
|
|
|
19 |
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
|
20 |
import static org.eclipse.jgit.lib.Constants.PACKED_REFS;
|
21 |
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
@@ -124,6 +125,8 @@ public class RefDirectory extends RefDatabase {
|
|
124 |
|
125 |
private final File gitDir;
|
126 |
|
|
|
|
|
127 |
final File refsDir;
|
128 |
|
129 |
final File packedRefsFile;
|
@@ -188,6 +191,7 @@ public class RefDirectory extends RefDatabase {
|
|
188 |
RefDirectory(RefDirectory refDb) {
|
189 |
parent = refDb.parent;
|
190 |
gitDir = refDb.gitDir;
|
|
|
191 |
refsDir = refDb.refsDir;
|
192 |
logsDir = refDb.logsDir;
|
193 |
logsRefsDir = refDb.logsRefsDir;
|
@@ -204,10 +208,11 @@ public class RefDirectory extends RefDatabase {
|
|
204 |
final FS fs = db.getFS();
|
205 |
parent = db;
|
206 |
gitDir = db.getDirectory();
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
|
|
211 |
|
212 |
looseRefs.set(RefList.<LooseRef> emptyList());
|
213 |
packedRefs.set(NO_PACKED_REFS);
|
@@ -1329,7 +1334,12 @@ File fileFor(String name) {
|
|
1329 |
name = name.substring(R_REFS.length());
|
1330 |
return new File(refsDir, name);
|
1331 |
}
|
1332 |
-
|
|
|
|
|
|
|
|
|
|
|
1333 |
}
|
1334 |
|
1335 |
static int levelsIn(String name) {
|
|
|
16 |
import static java.nio.charset.StandardCharsets.UTF_8;
|
17 |
import static org.eclipse.jgit.lib.Constants.HEAD;
|
18 |
import static org.eclipse.jgit.lib.Constants.LOGS;
|
19 |
+
import static org.eclipse.jgit.lib.Constants.L_LOGS;
|
20 |
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
|
21 |
import static org.eclipse.jgit.lib.Constants.PACKED_REFS;
|
22 |
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
|
|
125 |
|
126 |
private final File gitDir;
|
127 |
|
128 |
+
private final File gitCommonDir;
|
129 |
+
|
130 |
final File refsDir;
|
131 |
|
132 |
final File packedRefsFile;
|
|
|
191 |
RefDirectory(RefDirectory refDb) {
|
192 |
parent = refDb.parent;
|
193 |
gitDir = refDb.gitDir;
|
194 |
+
gitCommonDir = refDb.gitCommonDir;
|
195 |
refsDir = refDb.refsDir;
|
196 |
logsDir = refDb.logsDir;
|
197 |
logsRefsDir = refDb.logsRefsDir;
|
|
|
208 |
final FS fs = db.getFS();
|
209 |
parent = db;
|
210 |
gitDir = db.getDirectory();
|
211 |
+
gitCommonDir = db.getCommonDirectory();
|
212 |
+
refsDir = fs.resolve(gitCommonDir, R_REFS);
|
213 |
+
logsDir = fs.resolve(gitCommonDir, LOGS);
|
214 |
+
logsRefsDir = fs.resolve(gitCommonDir, L_LOGS + R_REFS);
|
215 |
+
packedRefsFile = fs.resolve(gitCommonDir, PACKED_REFS);
|
216 |
|
217 |
looseRefs.set(RefList.<LooseRef> emptyList());
|
218 |
packedRefs.set(NO_PACKED_REFS);
|
|
|
1334 |
name = name.substring(R_REFS.length());
|
1335 |
return new File(refsDir, name);
|
1336 |
}
|
1337 |
+
// HEAD needs to get resolved from git dir as resolving it from common dir
|
1338 |
+
// would always lead back to current default branch
|
1339 |
+
if (name.equals(HEAD)) {
|
1340 |
+
return new File(gitDir, name);
|
1341 |
+
}
|
1342 |
+
return new File(gitCommonDir, name);
|
1343 |
}
|
1344 |
|
1345 |
static int levelsIn(String name) {
|
@@ -10,6 +10,8 @@
|
|
10 |
|
11 |
package org.eclipse.jgit.internal.storage.file;
|
12 |
|
|
|
|
|
13 |
import java.io.File;
|
14 |
import java.io.FileNotFoundException;
|
15 |
import java.io.IOException;
|
@@ -37,7 +39,9 @@ class ReflogReaderImpl implements ReflogReader {
|
|
37 |
* {@code Ref} name
|
38 |
*/
|
39 |
ReflogReaderImpl(Repository db, String refname) {
|
40 |
-
|
|
|
|
|
41 |
}
|
42 |
|
43 |
/* (non-Javadoc)
|
|
|
10 |
|
11 |
package org.eclipse.jgit.internal.storage.file;
|
12 |
|
13 |
+
import static org.eclipse.jgit.lib.Constants.HEAD;
|
14 |
+
|
15 |
import java.io.File;
|
16 |
import java.io.FileNotFoundException;
|
17 |
import java.io.IOException;
|
|
|
39 |
* {@code Ref} name
|
40 |
*/
|
41 |
ReflogReaderImpl(Repository db, String refname) {
|
42 |
+
File logBaseDir = refname.equals(HEAD) ? db.getDirectory()
|
43 |
+
: db.getCommonDirectory();
|
44 |
+
logName = new File(logBaseDir, Constants.L_LOGS + refname);
|
45 |
}
|
46 |
|
47 |
/* (non-Javadoc)
|
@@ -1,71 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* Copyright (C) 2024, Thomas Wolf <twolf@apache.org> and others
|
3 |
-
*
|
4 |
-
* This program and the accompanying materials are made available under the
|
5 |
-
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
-
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
-
*
|
8 |
-
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
-
*/
|
10 |
-
package org.eclipse.jgit.lib;
|
11 |
-
|
12 |
-
import java.io.IOException;
|
13 |
-
import java.util.Arrays;
|
14 |
-
|
15 |
-
import org.eclipse.jgit.revwalk.RevCommit;
|
16 |
-
import org.eclipse.jgit.revwalk.RevObject;
|
17 |
-
import org.eclipse.jgit.revwalk.RevTag;
|
18 |
-
import org.eclipse.jgit.util.RawParseUtils;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Provides a base implementation of
|
22 |
-
* {@link GpgSignatureVerifier#verifySignature(RevObject, GpgConfig)}.
|
23 |
-
*
|
24 |
-
* @since 6.9
|
25 |
-
*/
|
26 |
-
public abstract class AbstractGpgSignatureVerifier
|
27 |
-
implements GpgSignatureVerifier {
|
28 |
-
|
29 |
-
@Override
|
30 |
-
public SignatureVerification verifySignature(RevObject object,
|
31 |
-
GpgConfig config) throws IOException {
|
32 |
-
if (object instanceof RevCommit) {
|
33 |
-
RevCommit commit = (RevCommit) object;
|
34 |
-
byte[] signatureData = commit.getRawGpgSignature();
|
35 |
-
if (signatureData == null) {
|
36 |
-
return null;
|
37 |
-
}
|
38 |
-
byte[] raw = commit.getRawBuffer();
|
39 |
-
// Now remove the GPG signature
|
40 |
-
byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
|
41 |
-
int start = RawParseUtils.headerStart(header, raw, 0);
|
42 |
-
if (start < 0) {
|
43 |
-
return null;
|
44 |
-
}
|
45 |
-
int end = RawParseUtils.nextLfSkippingSplitLines(raw, start);
|
46 |
-
// start is at the beginning of the header's content
|
47 |
-
start -= header.length + 1;
|
48 |
-
// end is on the terminating LF; we need to skip that, too
|
49 |
-
if (end < raw.length) {
|
50 |
-
end++;
|
51 |
-
}
|
52 |
-
byte[] data = new byte[raw.length - (end - start)];
|
53 |
-
System.arraycopy(raw, 0, data, 0, start);
|
54 |
-
System.arraycopy(raw, end, data, start, raw.length - end);
|
55 |
-
return verify(config, data, signatureData);
|
56 |
-
} else if (object instanceof RevTag) {
|
57 |
-
RevTag tag = (RevTag) object;
|
58 |
-
byte[] signatureData = tag.getRawGpgSignature();
|
59 |
-
if (signatureData == null) {
|
60 |
-
return null;
|
61 |
-
}
|
62 |
-
byte[] raw = tag.getRawBuffer();
|
63 |
-
// The signature is just tacked onto the end of the message, which
|
64 |
-
// is last in the buffer.
|
65 |
-
byte[] data = Arrays.copyOfRange(raw, 0,
|
66 |
-
raw.length - signatureData.length);
|
67 |
-
return verify(config, data, signatureData);
|
68 |
-
}
|
69 |
-
return null;
|
70 |
-
}
|
71 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -27,23 +27,6 @@
|
|
27 |
*/
|
28 |
public abstract class AnyObjectId implements Comparable<AnyObjectId> {
|
29 |
|
30 |
-
/**
|
31 |
-
* Compare two object identifier byte sequences for equality.
|
32 |
-
*
|
33 |
-
* @param firstObjectId
|
34 |
-
* the first identifier to compare. Must not be null.
|
35 |
-
* @param secondObjectId
|
36 |
-
* the second identifier to compare. Must not be null.
|
37 |
-
* @return true if the two identifiers are the same.
|
38 |
-
* @deprecated use {@link #isEqual(AnyObjectId, AnyObjectId)} instead
|
39 |
-
*/
|
40 |
-
@Deprecated
|
41 |
-
@SuppressWarnings("AmbiguousMethodReference")
|
42 |
-
public static boolean equals(final AnyObjectId firstObjectId,
|
43 |
-
final AnyObjectId secondObjectId) {
|
44 |
-
return isEqual(firstObjectId, secondObjectId);
|
45 |
-
}
|
46 |
-
|
47 |
/**
|
48 |
* Compare two object identifier byte sequences for equality.
|
49 |
*
|
|
|
27 |
*/
|
28 |
public abstract class AnyObjectId implements Comparable<AnyObjectId> {
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
/**
|
31 |
* Compare two object identifier byte sequences for equality.
|
32 |
*
|
@@ -13,13 +13,17 @@
|
|
13 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
|
14 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BARE;
|
15 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WORKTREE;
|
|
|
16 |
import static org.eclipse.jgit.lib.Constants.DOT_GIT;
|
17 |
import static org.eclipse.jgit.lib.Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY;
|
18 |
import static org.eclipse.jgit.lib.Constants.GIT_CEILING_DIRECTORIES_KEY;
|
|
|
19 |
import static org.eclipse.jgit.lib.Constants.GIT_DIR_KEY;
|
20 |
import static org.eclipse.jgit.lib.Constants.GIT_INDEX_FILE_KEY;
|
21 |
import static org.eclipse.jgit.lib.Constants.GIT_OBJECT_DIRECTORY_KEY;
|
22 |
import static org.eclipse.jgit.lib.Constants.GIT_WORK_TREE_KEY;
|
|
|
|
|
23 |
|
24 |
import java.io.File;
|
25 |
import java.io.IOException;
|
@@ -70,7 +74,21 @@ private static boolean isSymRef(byte[] ref) {
|
|
70 |
&& ref[7] == ' ';
|
71 |
}
|
72 |
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
throws IOException {
|
75 |
byte[] content = IO.readFully(dotGit);
|
76 |
if (!isSymRef(content)) {
|
@@ -102,6 +120,8 @@ private static File getSymRef(File workTree, File dotGit, FS fs)
|
|
102 |
|
103 |
private File gitDir;
|
104 |
|
|
|
|
|
105 |
private File objectDirectory;
|
106 |
|
107 |
private List<File> alternateObjectDirectories;
|
@@ -171,6 +191,30 @@ public File getGitDir() {
|
|
171 |
return gitDir;
|
172 |
}
|
173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
/**
|
175 |
* Set the directory storing the repository's objects.
|
176 |
*
|
@@ -396,9 +440,9 @@ public B setInitialBranch(String branch) throws InvalidRefNameException {
|
|
396 |
* Read standard Git environment variables and configure from those.
|
397 |
* <p>
|
398 |
* This method tries to read the standard Git environment variables, such as
|
399 |
-
* {@code GIT_DIR}
|
400 |
-
* instance. If an environment variable is set, it
|
401 |
-
* already set in this builder.
|
402 |
*
|
403 |
* @return {@code this} (for chaining calls).
|
404 |
*/
|
@@ -410,9 +454,9 @@ public B readEnvironment() {
|
|
410 |
* Read standard Git environment variables and configure from those.
|
411 |
* <p>
|
412 |
* This method tries to read the standard Git environment variables, such as
|
413 |
-
* {@code GIT_DIR}
|
414 |
-
* instance. If a property is already set in the
|
415 |
-
* variable is not used.
|
416 |
*
|
417 |
* @param sr
|
418 |
* the SystemReader abstraction to access the environment.
|
@@ -425,6 +469,13 @@ public B readEnvironment(SystemReader sr) {
|
|
425 |
setGitDir(new File(val));
|
426 |
}
|
427 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
if (getObjectDirectory() == null) {
|
429 |
String val = sr.getenv(GIT_OBJECT_DIRECTORY_KEY);
|
430 |
if (val != null)
|
@@ -601,6 +652,7 @@ public B findGitDir(File current) {
|
|
601 |
public B setup() throws IllegalArgumentException, IOException {
|
602 |
requireGitDirOrWorkTree();
|
603 |
setupGitDir();
|
|
|
604 |
setupWorkTree();
|
605 |
setupInternals();
|
606 |
return self();
|
@@ -657,6 +709,20 @@ protected void setupGitDir() throws IOException {
|
|
657 |
}
|
658 |
}
|
659 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
660 |
/**
|
661 |
* Perform standard work-tree initialization.
|
662 |
* <p>
|
@@ -695,8 +761,12 @@ protected void setupWorkTree() throws IOException {
|
|
695 |
* the repository could not be accessed
|
696 |
*/
|
697 |
protected void setupInternals() throws IOException {
|
698 |
-
if (getObjectDirectory() == null
|
699 |
-
|
|
|
|
|
|
|
|
|
700 |
}
|
701 |
|
702 |
/**
|
@@ -723,12 +793,13 @@ protected Config getConfig() throws IOException {
|
|
723 |
* the configuration is not available.
|
724 |
*/
|
725 |
protected Config loadConfig() throws IOException {
|
726 |
-
|
|
|
727 |
// We only want the repository's configuration file, and not
|
728 |
// the user file, as these parameters must be unique to this
|
729 |
// repository and not inherited from other files.
|
730 |
//
|
731 |
-
File path = safeFS().resolve(
|
732 |
FileBasedConfig cfg = new FileBasedConfig(path, safeFS());
|
733 |
try {
|
734 |
cfg.load();
|
@@ -749,8 +820,29 @@ private File guessWorkTreeOrFail() throws IOException {
|
|
749 |
//
|
750 |
String path = cfg.getString(CONFIG_CORE_SECTION, null,
|
751 |
CONFIG_KEY_WORKTREE);
|
752 |
-
if (path != null)
|
753 |
return safeFS().resolve(getGitDir(), path).getCanonicalFile();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
754 |
|
755 |
// If core.bare is set, honor its value. Assume workTree is
|
756 |
// the parent directory of the repository.
|
|
|
13 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
|
14 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BARE;
|
15 |
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WORKTREE;
|
16 |
+
import static org.eclipse.jgit.lib.Constants.CONFIG;
|
17 |
import static org.eclipse.jgit.lib.Constants.DOT_GIT;
|
18 |
import static org.eclipse.jgit.lib.Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY;
|
19 |
import static org.eclipse.jgit.lib.Constants.GIT_CEILING_DIRECTORIES_KEY;
|
20 |
+
import static org.eclipse.jgit.lib.Constants.GIT_COMMON_DIR_KEY;
|
21 |
import static org.eclipse.jgit.lib.Constants.GIT_DIR_KEY;
|
22 |
import static org.eclipse.jgit.lib.Constants.GIT_INDEX_FILE_KEY;
|
23 |
import static org.eclipse.jgit.lib.Constants.GIT_OBJECT_DIRECTORY_KEY;
|
24 |
import static org.eclipse.jgit.lib.Constants.GIT_WORK_TREE_KEY;
|
25 |
+
import static org.eclipse.jgit.lib.Constants.OBJECTS;
|
26 |
+
import static org.eclipse.jgit.lib.Constants.GITDIR_FILE;
|
27 |
|
28 |
import java.io.File;
|
29 |
import java.io.IOException;
|
|
|
74 |
&& ref[7] == ' ';
|
75 |
}
|
76 |
|
77 |
+
/**
|
78 |
+
* Read symbolic reference file
|
79 |
+
*
|
80 |
+
* @param workTree
|
81 |
+
* the work tree path
|
82 |
+
* @param dotGit
|
83 |
+
* the .git file
|
84 |
+
* @param fs
|
85 |
+
* th FS util
|
86 |
+
* @return the file read from symbolic reference file
|
87 |
+
* @throws java.io.IOException
|
88 |
+
* the dotGit file is invalid reference
|
89 |
+
* @since 7.0
|
90 |
+
*/
|
91 |
+
static File getSymRef(File workTree, File dotGit, FS fs)
|
92 |
throws IOException {
|
93 |
byte[] content = IO.readFully(dotGit);
|
94 |
if (!isSymRef(content)) {
|
|
|
120 |
|
121 |
private File gitDir;
|
122 |
|
123 |
+
private File gitCommonDir;
|
124 |
+
|
125 |
private File objectDirectory;
|
126 |
|
127 |
private List<File> alternateObjectDirectories;
|
|
|
191 |
return gitDir;
|
192 |
}
|
193 |
|
194 |
+
/**
|
195 |
+
* Set common dir.
|
196 |
+
*
|
197 |
+
* @param gitCommonDir
|
198 |
+
* {@code GIT_COMMON_DIR}, the common repository meta directory.
|
199 |
+
* @return {@code this} (for chaining calls).
|
200 |
+
* @since 7.0
|
201 |
+
*/
|
202 |
+
public B setGitCommonDir(File gitCommonDir) {
|
203 |
+
this.gitCommonDir = gitCommonDir;
|
204 |
+
this.config = null;
|
205 |
+
return self();
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Get common dir.
|
210 |
+
*
|
211 |
+
* @return common dir; null if not set.
|
212 |
+
* @since 7.0
|
213 |
+
*/
|
214 |
+
public File getGitCommonDir() {
|
215 |
+
return gitCommonDir;
|
216 |
+
}
|
217 |
+
|
218 |
/**
|
219 |
* Set the directory storing the repository's objects.
|
220 |
*
|
|
|
440 |
* Read standard Git environment variables and configure from those.
|
441 |
* <p>
|
442 |
* This method tries to read the standard Git environment variables, such as
|
443 |
+
* {@code GIT_DIR}, {@code GIT_COMMON_DIR}, {@code GIT_WORK_TREE} etc. to
|
444 |
+
* configure this builder instance. If an environment variable is set, it
|
445 |
+
* overrides the value already set in this builder.
|
446 |
*
|
447 |
* @return {@code this} (for chaining calls).
|
448 |
*/
|
|
|
454 |
* Read standard Git environment variables and configure from those.
|
455 |
* <p>
|
456 |
* This method tries to read the standard Git environment variables, such as
|
457 |
+
* {@code GIT_DIR}, {@code GIT_COMMON_DIR}, {@code GIT_WORK_TREE} etc. to
|
458 |
+
* configure this builder instance. If a property is already set in the
|
459 |
+
* builder, the environment variable is not used.
|
460 |
*
|
461 |
* @param sr
|
462 |
* the SystemReader abstraction to access the environment.
|
|
|
469 |
setGitDir(new File(val));
|
470 |
}
|
471 |
|
472 |
+
if (getGitCommonDir() == null) {
|
473 |
+
String val = sr.getenv(GIT_COMMON_DIR_KEY);
|
474 |
+
if (val != null) {
|
475 |
+
setGitCommonDir(new File(val));
|
476 |
+
}
|
477 |
+
}
|
478 |
+
|
479 |
if (getObjectDirectory() == null) {
|
480 |
String val = sr.getenv(GIT_OBJECT_DIRECTORY_KEY);
|
481 |
if (val != null)
|
|
|
652 |
public B setup() throws IllegalArgumentException, IOException {
|
653 |
requireGitDirOrWorkTree();
|
654 |
setupGitDir();
|
655 |
+
setupCommonDir();
|
656 |
setupWorkTree();
|
657 |
setupInternals();
|
658 |
return self();
|
|
|
709 |
}
|
710 |
}
|
711 |
|
712 |
+
/**
|
713 |
+
* Perform standard common dir initialization.
|
714 |
+
*
|
715 |
+
* @throws java.io.IOException
|
716 |
+
* the repository could not be accessed
|
717 |
+
* @since 7.0
|
718 |
+
*/
|
719 |
+
protected void setupCommonDir() throws IOException {
|
720 |
+
// no gitCommonDir? Try to get it from gitDir
|
721 |
+
if (getGitCommonDir() == null) {
|
722 |
+
setGitCommonDir(safeFS().getCommonDir(getGitDir()));
|
723 |
+
}
|
724 |
+
}
|
725 |
+
|
726 |
/**
|
727 |
* Perform standard work-tree initialization.
|
728 |
* <p>
|
|
|
761 |
* the repository could not be accessed
|
762 |
*/
|
763 |
protected void setupInternals() throws IOException {
|
764 |
+
if (getObjectDirectory() == null) {
|
765 |
+
File commonDir = getGitCommonDir();
|
766 |
+
if (commonDir != null) {
|
767 |
+
setObjectDirectory(safeFS().resolve(commonDir, OBJECTS));
|
768 |
+
}
|
769 |
+
}
|
770 |
}
|
771 |
|
772 |
/**
|
|
|
793 |
* the configuration is not available.
|
794 |
*/
|
795 |
protected Config loadConfig() throws IOException {
|
796 |
+
File commonDir = getGitCommonDir();
|
797 |
+
if (commonDir != null) {
|
798 |
// We only want the repository's configuration file, and not
|
799 |
// the user file, as these parameters must be unique to this
|
800 |
// repository and not inherited from other files.
|
801 |
//
|
802 |
+
File path = safeFS().resolve(commonDir, CONFIG);
|
803 |
FileBasedConfig cfg = new FileBasedConfig(path, safeFS());
|
804 |
try {
|
805 |
cfg.load();
|
|
|
820 |
//
|
821 |
String path = cfg.getString(CONFIG_CORE_SECTION, null,
|
822 |
CONFIG_KEY_WORKTREE);
|
823 |
+
if (path != null) {
|
824 |
return safeFS().resolve(getGitDir(), path).getCanonicalFile();
|
825 |
+
}
|
826 |
+
|
827 |
+
/*
|
828 |
+
* We are in worktree's $GIT_DIR folder
|
829 |
+
* ".git/worktrees/<worktree-name>" and want to get the working
|
830 |
+
* tree (checkout) path; so here we have an opposite link in file
|
831 |
+
* "gitdir" showing to the ".git" file located in the working tree read
|
832 |
+
* it and convert it to absolute path if it's relative
|
833 |
+
*/
|
834 |
+
File gitDirFile = new File(getGitDir(), GITDIR_FILE);
|
835 |
+
if (gitDirFile.isFile()) {
|
836 |
+
String workDirPath = new String(IO.readFully(gitDirFile)).trim();
|
837 |
+
File workTreeDotGitFile = new File(workDirPath);
|
838 |
+
if (!workTreeDotGitFile.isAbsolute()) {
|
839 |
+
workTreeDotGitFile = new File(getGitDir(), workDirPath)
|
840 |
+
.getCanonicalFile();
|
841 |
+
}
|
842 |
+
if (workTreeDotGitFile != null) {
|
843 |
+
return workTreeDotGitFile.getParentFile();
|
844 |
+
}
|
845 |
+
}
|
846 |
|
847 |
// If core.bare is set, honor its value. Assume workTree is
|
848 |
// the parent directory of the repository.
|
@@ -194,19 +194,6 @@ public void addParentId(AnyObjectId additionalParent) {
|
|
194 |
}
|
195 |
}
|
196 |
|
197 |
-
/**
|
198 |
-
* Set the encoding for the commit information.
|
199 |
-
*
|
200 |
-
* @param encodingName
|
201 |
-
* the encoding name. See
|
202 |
-
* {@link java.nio.charset.Charset#forName(String)}.
|
203 |
-
* @deprecated use {@link #setEncoding(Charset)} instead.
|
204 |
-
*/
|
205 |
-
@Deprecated
|
206 |
-
public void setEncoding(String encodingName) {
|
207 |
-
setEncoding(Charset.forName(encodingName));
|
208 |
-
}
|
209 |
-
|
210 |
@Override
|
211 |
public byte[] build() throws UnsupportedEncodingException {
|
212 |
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
|
194 |
}
|
195 |
}
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
@Override
|
198 |
public byte[] build() throws UnsupportedEncodingException {
|
199 |
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
@@ -77,6 +77,13 @@ public final class ConfigConstants {
|
|
77 |
/** The "dfs" section */
|
78 |
public static final String CONFIG_DFS_SECTION = "dfs";
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
/**
|
81 |
* The "receive" section
|
82 |
* @since 4.6
|
@@ -331,6 +338,13 @@ public final class ConfigConstants {
|
|
331 |
/** The "deltaBaseCacheLimit" key */
|
332 |
public static final String CONFIG_KEY_DELTA_BASE_CACHE_LIMIT = "deltaBaseCacheLimit";
|
333 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
/**
|
335 |
* The "symlinks" key
|
336 |
* @since 3.3
|
@@ -344,12 +358,6 @@ public final class ConfigConstants {
|
|
344 |
*/
|
345 |
public static final String CONFIG_KEY_STREAM_FILE_THRESHOLD = "streamFileThreshold";
|
346 |
|
347 |
-
/**
|
348 |
-
* @deprecated typo, use CONFIG_KEY_STREAM_FILE_THRESHOLD instead
|
349 |
-
*/
|
350 |
-
@Deprecated(since = "6.8")
|
351 |
-
public static final String CONFIG_KEY_STREAM_FILE_TRESHOLD = CONFIG_KEY_STREAM_FILE_THRESHOLD;
|
352 |
-
|
353 |
/**
|
354 |
* The "packedGitMmap" key
|
355 |
* @since 5.1.13
|
@@ -1012,4 +1020,11 @@ public final class ConfigConstants {
|
|
1012 |
* @since 6.7
|
1013 |
*/
|
1014 |
public static final String CONFIG_KEY_READ_CHANGED_PATHS = "readChangedPaths";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1015 |
}
|
|
|
77 |
/** The "dfs" section */
|
78 |
public static final String CONFIG_DFS_SECTION = "dfs";
|
79 |
|
80 |
+
/**
|
81 |
+
* The dfs cache subsection prefix.
|
82 |
+
*
|
83 |
+
* @since 7.0
|
84 |
+
*/
|
85 |
+
public static final String CONFIG_DFS_CACHE_PREFIX = "dfs.";
|
86 |
+
|
87 |
/**
|
88 |
* The "receive" section
|
89 |
* @since 4.6
|
|
|
338 |
/** The "deltaBaseCacheLimit" key */
|
339 |
public static final String CONFIG_KEY_DELTA_BASE_CACHE_LIMIT = "deltaBaseCacheLimit";
|
340 |
|
341 |
+
/**
|
342 |
+
* The "packExtensions" key
|
343 |
+
*
|
344 |
+
* @since 7.0
|
345 |
+
**/
|
346 |
+
public static final String CONFIG_KEY_PACK_EXTENSIONS = "packExtensions";
|
347 |
+
|
348 |
/**
|
349 |
* The "symlinks" key
|
350 |
* @since 3.3
|
|
|
358 |
*/
|
359 |
public static final String CONFIG_KEY_STREAM_FILE_THRESHOLD = "streamFileThreshold";
|
360 |
|
|
|
|
|
|
|
|
|
|
|
|
|
361 |
/**
|
362 |
* The "packedGitMmap" key
|
363 |
* @since 5.1.13
|
|
|
1020 |
* @since 6.7
|
1021 |
*/
|
1022 |
public static final String CONFIG_KEY_READ_CHANGED_PATHS = "readChangedPaths";
|
1023 |
+
|
1024 |
+
/**
|
1025 |
+
* The "useObjectSizeIndex" key
|
1026 |
+
*
|
1027 |
+
* @since 7.0
|
1028 |
+
*/
|
1029 |
+
public static final String CONFIG_KEY_USE_OBJECT_SIZE_INDEX = "useObjectSizeIndex";
|
1030 |
}
|
@@ -15,7 +15,6 @@
|
|
15 |
import static java.nio.charset.StandardCharsets.UTF_8;
|
16 |
|
17 |
import java.nio.ByteBuffer;
|
18 |
-
import java.nio.charset.Charset;
|
19 |
import java.security.MessageDigest;
|
20 |
import java.security.NoSuchAlgorithmException;
|
21 |
import java.text.MessageFormat;
|
@@ -203,24 +202,6 @@ public final class Constants {
|
|
203 |
*/
|
204 |
public static final byte[] PACK_SIGNATURE = { 'P', 'A', 'C', 'K' };
|
205 |
|
206 |
-
/**
|
207 |
-
* Native character encoding for commit messages, file names...
|
208 |
-
*
|
209 |
-
* @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8} directly
|
210 |
-
* instead.
|
211 |
-
*/
|
212 |
-
@Deprecated
|
213 |
-
public static final Charset CHARSET;
|
214 |
-
|
215 |
-
/**
|
216 |
-
* Native character encoding for commit messages, file names...
|
217 |
-
*
|
218 |
-
* @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8} directly
|
219 |
-
* instead.
|
220 |
-
*/
|
221 |
-
@Deprecated
|
222 |
-
public static final String CHARACTER_ENCODING;
|
223 |
-
|
224 |
/** Default main branch name */
|
225 |
public static final String MASTER = "master";
|
226 |
|
@@ -272,6 +253,20 @@ public final class Constants {
|
|
272 |
/** Info refs folder */
|
273 |
public static final String INFO_REFS = "info/refs";
|
274 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
/**
|
276 |
* Info alternates file (goes under OBJECTS)
|
277 |
* @since 5.5
|
@@ -357,6 +352,14 @@ public final class Constants {
|
|
357 |
*/
|
358 |
public static final String GIT_DIR_KEY = "GIT_DIR";
|
359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
/**
|
361 |
* The environment variable that tells us which directory is the working
|
362 |
* directory.
|
@@ -458,6 +461,36 @@ public final class Constants {
|
|
458 |
*/
|
459 |
public static final String GITDIR = "gitdir: ";
|
460 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
461 |
/**
|
462 |
* Name of the folder (inside gitDir) where submodules are stored
|
463 |
*
|
@@ -493,6 +526,27 @@ public final class Constants {
|
|
493 |
*/
|
494 |
public static final String ATTR_BUILTIN_BINARY_MERGER = "binary"; //$NON-NLS-1$
|
495 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
/**
|
497 |
* Create a new digest function for objects.
|
498 |
*
|
@@ -672,13 +726,12 @@ public static byte[] encodeASCII(String s) {
|
|
672 |
}
|
673 |
|
674 |
/**
|
675 |
-
* Convert a string to a byte array in the standard character encoding.
|
676 |
*
|
677 |
* @param str
|
678 |
* the string to convert. May contain any Unicode characters.
|
679 |
* @return a byte array representing the requested string, encoded using the
|
680 |
* default character encoding (UTF-8).
|
681 |
-
* @see #CHARACTER_ENCODING
|
682 |
*/
|
683 |
public static byte[] encode(String str) {
|
684 |
final ByteBuffer bb = UTF_8.encode(str);
|
@@ -697,8 +750,6 @@ public static byte[] encode(String str) {
|
|
697 |
static {
|
698 |
if (OBJECT_ID_LENGTH != newMessageDigest().getDigestLength())
|
699 |
throw new LinkageError(JGitText.get().incorrectOBJECT_ID_LENGTH);
|
700 |
-
CHARSET = UTF_8;
|
701 |
-
CHARACTER_ENCODING = UTF_8.name();
|
702 |
}
|
703 |
|
704 |
/** name of the file containing the commit msg for a merge commit */
|
|
|
15 |
import static java.nio.charset.StandardCharsets.UTF_8;
|
16 |
|
17 |
import java.nio.ByteBuffer;
|
|
|
18 |
import java.security.MessageDigest;
|
19 |
import java.security.NoSuchAlgorithmException;
|
20 |
import java.text.MessageFormat;
|
|
|
202 |
*/
|
203 |
public static final byte[] PACK_SIGNATURE = { 'P', 'A', 'C', 'K' };
|
204 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
/** Default main branch name */
|
206 |
public static final String MASTER = "master";
|
207 |
|
|
|
253 |
/** Info refs folder */
|
254 |
public static final String INFO_REFS = "info/refs";
|
255 |
|
256 |
+
/**
|
257 |
+
* Name of heads folder or file in refs.
|
258 |
+
*
|
259 |
+
* @since 7.0
|
260 |
+
*/
|
261 |
+
public static final String HEADS = "heads";
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Prefix for any log.
|
265 |
+
*
|
266 |
+
* @since 7.0
|
267 |
+
*/
|
268 |
+
public static final String L_LOGS = LOGS + "/";
|
269 |
+
|
270 |
/**
|
271 |
* Info alternates file (goes under OBJECTS)
|
272 |
* @since 5.5
|
|
|
352 |
*/
|
353 |
public static final String GIT_DIR_KEY = "GIT_DIR";
|
354 |
|
355 |
+
/**
|
356 |
+
* The environment variable that tells us which directory is the common
|
357 |
+
* ".git" directory.
|
358 |
+
*
|
359 |
+
* @since 7.0
|
360 |
+
*/
|
361 |
+
public static final String GIT_COMMON_DIR_KEY = "GIT_COMMON_DIR";
|
362 |
+
|
363 |
/**
|
364 |
* The environment variable that tells us which directory is the working
|
365 |
* directory.
|
|
|
461 |
*/
|
462 |
public static final String GITDIR = "gitdir: ";
|
463 |
|
464 |
+
/**
|
465 |
+
* Name of the file (inside gitDir) that references the worktree's .git
|
466 |
+
* file (opposite link).
|
467 |
+
*
|
468 |
+
* .git/worktrees/<worktree-name>/gitdir
|
469 |
+
*
|
470 |
+
* A text file containing the absolute path back to the .git file that
|
471 |
+
* points here. This file is used to verify if the linked repository has been
|
472 |
+
* manually removed in which case this directory is no longer needed.
|
473 |
+
* The modification time (mtime) of this file should be updated each time
|
474 |
+
* the linked repository is accessed.
|
475 |
+
*
|
476 |
+
* @since 7.0
|
477 |
+
*/
|
478 |
+
public static final String GITDIR_FILE = "gitdir";
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Name of the file (inside gitDir) that has reference to $GIT_COMMON_DIR.
|
482 |
+
*
|
483 |
+
* .git/worktrees/<worktree-name>/commondir
|
484 |
+
*
|
485 |
+
* If this file exists, $GIT_COMMON_DIR will be set to the path specified in
|
486 |
+
* this file unless it is explicitly set. If the specified path is relative,
|
487 |
+
* it is relative to $GIT_DIR. The repository with commondir is incomplete
|
488 |
+
* without the repository pointed by "commondir".
|
489 |
+
*
|
490 |
+
* @since 7.0
|
491 |
+
*/
|
492 |
+
public static final String COMMONDIR_FILE = "commondir";
|
493 |
+
|
494 |
/**
|
495 |
* Name of the folder (inside gitDir) where submodules are stored
|
496 |
*
|
|
|
526 |
*/
|
527 |
public static final String ATTR_BUILTIN_BINARY_MERGER = "binary"; //$NON-NLS-1$
|
528 |
|
529 |
+
/**
|
530 |
+
* Prefix of a GPG signature.
|
531 |
+
*
|
532 |
+
* @since 7.0
|
533 |
+
*/
|
534 |
+
public static final String GPG_SIGNATURE_PREFIX = "-----BEGIN PGP SIGNATURE-----"; //$NON-NLS-1$
|
535 |
+
|
536 |
+
/**
|
537 |
+
* Prefix of a CMS signature (X.509, S/MIME).
|
538 |
+
*
|
539 |
+
* @since 7.0
|
540 |
+
*/
|
541 |
+
public static final String CMS_SIGNATURE_PREFIX = "-----BEGIN SIGNED MESSAGE-----"; //$NON-NLS-1$
|
542 |
+
|
543 |
+
/**
|
544 |
+
* Prefix of an SSH signature.
|
545 |
+
*
|
546 |
+
* @since 7.0
|
547 |
+
*/
|
548 |
+
public static final String SSH_SIGNATURE_PREFIX = "-----BEGIN SSH SIGNATURE-----"; //$NON-NLS-1$
|
549 |
+
|
550 |
/**
|
551 |
* Create a new digest function for objects.
|
552 |
*
|
|
|
726 |
}
|
727 |
|
728 |
/**
|
729 |
+
* Convert a string to a byte array in the standard character encoding UTF8.
|
730 |
*
|
731 |
* @param str
|
732 |
* the string to convert. May contain any Unicode characters.
|
733 |
* @return a byte array representing the requested string, encoded using the
|
734 |
* default character encoding (UTF-8).
|
|
|
735 |
*/
|
736 |
public static byte[] encode(String str) {
|
737 |
final ByteBuffer bb = UTF_8.encode(str);
|
|
|
750 |
static {
|
751 |
if (OBJECT_ID_LENGTH != newMessageDigest().getDigestLength())
|
752 |
throw new LinkageError(JGitText.get().incorrectOBJECT_ID_LENGTH);
|
|
|
|
|
753 |
}
|
754 |
|
755 |
/** name of the file containing the commit msg for a merge commit */
|
@@ -163,8 +163,6 @@ public enum TrustLooseRefStat {
|
|
163 |
|
164 |
private final int packIndexVersion;
|
165 |
|
166 |
-
private final LogRefUpdates logAllRefUpdates;
|
167 |
-
|
168 |
private final String excludesfile;
|
169 |
|
170 |
private final String attributesfile;
|
@@ -205,9 +203,6 @@ private CoreConfig(Config rc) {
|
|
205 |
ConfigConstants.CONFIG_KEY_COMPRESSION, DEFAULT_COMPRESSION);
|
206 |
packIndexVersion = rc.getInt(ConfigConstants.CONFIG_PACK_SECTION,
|
207 |
ConfigConstants.CONFIG_KEY_INDEXVERSION, 2);
|
208 |
-
logAllRefUpdates = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
|
209 |
-
ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES,
|
210 |
-
LogRefUpdates.TRUE);
|
211 |
excludesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, null,
|
212 |
ConfigConstants.CONFIG_KEY_EXCLUDESFILE);
|
213 |
attributesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION,
|
@@ -235,20 +230,6 @@ public int getPackIndexVersion() {
|
|
235 |
return packIndexVersion;
|
236 |
}
|
237 |
|
238 |
-
/**
|
239 |
-
* Whether to log all refUpdates
|
240 |
-
*
|
241 |
-
* @return whether to log all refUpdates
|
242 |
-
* @deprecated since 5.6; default value depends on whether the repository is
|
243 |
-
* bare. Use
|
244 |
-
* {@link Config#getEnum(String, String, String, Enum)}
|
245 |
-
* directly.
|
246 |
-
*/
|
247 |
-
@Deprecated
|
248 |
-
public boolean isLogAllRefUpdates() {
|
249 |
-
return !LogRefUpdates.FALSE.equals(logAllRefUpdates);
|
250 |
-
}
|
251 |
-
|
252 |
/**
|
253 |
* Get path of excludesfile
|
254 |
*
|
|
|
163 |
|
164 |
private final int packIndexVersion;
|
165 |
|
|
|
|
|
166 |
private final String excludesfile;
|
167 |
|
168 |
private final String attributesfile;
|
|
|
203 |
ConfigConstants.CONFIG_KEY_COMPRESSION, DEFAULT_COMPRESSION);
|
204 |
packIndexVersion = rc.getInt(ConfigConstants.CONFIG_PACK_SECTION,
|
205 |
ConfigConstants.CONFIG_KEY_INDEXVERSION, 2);
|
|
|
|
|
|
|
206 |
excludesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, null,
|
207 |
ConfigConstants.CONFIG_KEY_EXCLUDESFILE);
|
208 |
attributesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION,
|
|
|
230 |
return packIndexVersion;
|
231 |
}
|
232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
/**
|
234 |
* Get path of excludesfile
|
235 |
*
|
@@ -24,7 +24,13 @@ public enum GpgFormat implements Config.ConfigEnum {
|
|
24 |
/** Value for openpgp */
|
25 |
OPENPGP("openpgp"), //$NON-NLS-1$
|
26 |
/** Value for x509 */
|
27 |
-
X509("x509")
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
private final String configValue;
|
30 |
|
@@ -55,27 +61,6 @@ public String toConfigValue() {
|
|
55 |
|
56 |
private final boolean forceAnnotated;
|
57 |
|
58 |
-
/**
|
59 |
-
* Create a {@link GpgConfig} with the given parameters and default
|
60 |
-
* {@code true} for signing commits and {@code false} for tags.
|
61 |
-
*
|
62 |
-
* @param keySpec
|
63 |
-
* to use
|
64 |
-
* @param format
|
65 |
-
* to use
|
66 |
-
* @param gpgProgram
|
67 |
-
* to use
|
68 |
-
* @since 5.11
|
69 |
-
*/
|
70 |
-
public GpgConfig(String keySpec, GpgFormat format, String gpgProgram) {
|
71 |
-
keyFormat = format;
|
72 |
-
signingKey = keySpec;
|
73 |
-
program = gpgProgram;
|
74 |
-
signCommits = true;
|
75 |
-
signAllTags = false;
|
76 |
-
forceAnnotated = false;
|
77 |
-
}
|
78 |
-
|
79 |
/**
|
80 |
* Create a new GPG config that reads the configuration from config.
|
81 |
*
|
@@ -91,10 +76,11 @@ public GpgConfig(Config config) {
|
|
91 |
|
92 |
String exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION,
|
93 |
keyFormat.toConfigValue(), ConfigConstants.CONFIG_KEY_PROGRAM);
|
94 |
-
if (exe == null) {
|
95 |
exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION, null,
|
96 |
ConfigConstants.CONFIG_KEY_PROGRAM);
|
97 |
}
|
|
|
98 |
program = exe;
|
99 |
signCommits = config.getBoolean(ConfigConstants.CONFIG_COMMIT_SECTION,
|
100 |
ConfigConstants.CONFIG_KEY_GPGSIGN, false);
|
|
|
24 |
/** Value for openpgp */
|
25 |
OPENPGP("openpgp"), //$NON-NLS-1$
|
26 |
/** Value for x509 */
|
27 |
+
X509("x509"), //$NON-NLS-1$
|
28 |
+
/**
|
29 |
+
* Value for ssh.
|
30 |
+
*
|
31 |
+
* @since 7.0
|
32 |
+
*/
|
33 |
+
SSH("ssh"); //$NON-NLS-1$
|
34 |
|
35 |
private final String configValue;
|
36 |
|
|
|
61 |
|
62 |
private final boolean forceAnnotated;
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
/**
|
65 |
* Create a new GPG config that reads the configuration from config.
|
66 |
*
|
|
|
76 |
|
77 |
String exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION,
|
78 |
keyFormat.toConfigValue(), ConfigConstants.CONFIG_KEY_PROGRAM);
|
79 |
+
if (exe == null && GpgFormat.OPENPGP.equals(keyFormat)) {
|
80 |
exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION, null,
|
81 |
ConfigConstants.CONFIG_KEY_PROGRAM);
|
82 |
}
|
83 |
+
|
84 |
program = exe;
|
85 |
signCommits = config.getBoolean(ConfigConstants.CONFIG_COMMIT_SECTION,
|
86 |
ConfigConstants.CONFIG_KEY_GPGSIGN, false);
|
@@ -1,95 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
|
3 |
-
*
|
4 |
-
* This program and the accompanying materials are made available under the
|
5 |
-
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
-
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
-
*
|
8 |
-
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
-
*/
|
10 |
-
package org.eclipse.jgit.lib;
|
11 |
-
|
12 |
-
import org.eclipse.jgit.annotations.NonNull;
|
13 |
-
import org.eclipse.jgit.annotations.Nullable;
|
14 |
-
import org.eclipse.jgit.api.errors.CanceledException;
|
15 |
-
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
|
16 |
-
import org.eclipse.jgit.transport.CredentialsProvider;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Creates GPG signatures for Git objects.
|
20 |
-
*
|
21 |
-
* @since 5.11
|
22 |
-
*/
|
23 |
-
public interface GpgObjectSigner {
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Signs the specified object.
|
27 |
-
*
|
28 |
-
* <p>
|
29 |
-
* Implementors should obtain the payload for signing from the specified
|
30 |
-
* object via {@link ObjectBuilder#build()} and create a proper
|
31 |
-
* {@link GpgSignature}. The generated signature must be set on the
|
32 |
-
* specified {@code object} (see
|
33 |
-
* {@link ObjectBuilder#setGpgSignature(GpgSignature)}).
|
34 |
-
* </p>
|
35 |
-
* <p>
|
36 |
-
* Any existing signature on the object must be discarded prior obtaining
|
37 |
-
* the payload via {@link ObjectBuilder#build()}.
|
38 |
-
* </p>
|
39 |
-
*
|
40 |
-
* @param object
|
41 |
-
* the object to sign (must not be {@code null} and must be
|
42 |
-
* complete to allow proper calculation of payload)
|
43 |
-
* @param gpgSigningKey
|
44 |
-
* the signing key to locate (passed as is to the GPG signing
|
45 |
-
* tool as is; eg., value of <code>user.signingkey</code>)
|
46 |
-
* @param committer
|
47 |
-
* the signing identity (to help with key lookup in case signing
|
48 |
-
* key is not specified)
|
49 |
-
* @param credentialsProvider
|
50 |
-
* provider to use when querying for signing key credentials (eg.
|
51 |
-
* passphrase)
|
52 |
-
* @param config
|
53 |
-
* GPG settings from the git config
|
54 |
-
* @throws CanceledException
|
55 |
-
* when signing was canceled (eg., user aborted when entering
|
56 |
-
* passphrase)
|
57 |
-
* @throws UnsupportedSigningFormatException
|
58 |
-
* if a config is given and the wanted key format is not
|
59 |
-
* supported
|
60 |
-
*/
|
61 |
-
void signObject(@NonNull ObjectBuilder object,
|
62 |
-
@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
|
63 |
-
CredentialsProvider credentialsProvider, GpgConfig config)
|
64 |
-
throws CanceledException, UnsupportedSigningFormatException;
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Indicates if a signing key is available for the specified committer
|
68 |
-
* and/or signing key.
|
69 |
-
*
|
70 |
-
* @param gpgSigningKey
|
71 |
-
* the signing key to locate (passed as is to the GPG signing
|
72 |
-
* tool as is; eg., value of <code>user.signingkey</code>)
|
73 |
-
* @param committer
|
74 |
-
* the signing identity (to help with key lookup in case signing
|
75 |
-
* key is not specified)
|
76 |
-
* @param credentialsProvider
|
77 |
-
* provider to use when querying for signing key credentials (eg.
|
78 |
-
* passphrase)
|
79 |
-
* @param config
|
80 |
-
* GPG settings from the git config
|
81 |
-
* @return <code>true</code> if a signing key is available,
|
82 |
-
* <code>false</code> otherwise
|
83 |
-
* @throws CanceledException
|
84 |
-
* when signing was canceled (eg., user aborted when entering
|
85 |
-
* passphrase)
|
86 |
-
* @throws UnsupportedSigningFormatException
|
87 |
-
* if a config is given and the wanted key format is not
|
88 |
-
* supported
|
89 |
-
*/
|
90 |
-
public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey,
|
91 |
-
@NonNull PersonIdent committer,
|
92 |
-
CredentialsProvider credentialsProvider, GpgConfig config)
|
93 |
-
throws CanceledException, UnsupportedSigningFormatException;
|
94 |
-
|
95 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,184 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
-
*
|
4 |
-
* This program and the accompanying materials are made available under the
|
5 |
-
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
-
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
-
*
|
8 |
-
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
-
*/
|
10 |
-
package org.eclipse.jgit.lib;
|
11 |
-
|
12 |
-
import java.io.IOException;
|
13 |
-
import java.util.Date;
|
14 |
-
|
15 |
-
import org.eclipse.jgit.annotations.NonNull;
|
16 |
-
import org.eclipse.jgit.annotations.Nullable;
|
17 |
-
import org.eclipse.jgit.api.errors.JGitInternalException;
|
18 |
-
import org.eclipse.jgit.revwalk.RevObject;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* A {@code GpgSignatureVerifier} can verify GPG signatures on git commits and
|
22 |
-
* tags.
|
23 |
-
*
|
24 |
-
* @since 5.11
|
25 |
-
*/
|
26 |
-
public interface GpgSignatureVerifier {
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Verifies the signature on a signed commit or tag.
|
30 |
-
*
|
31 |
-
* @param object
|
32 |
-
* to verify
|
33 |
-
* @param config
|
34 |
-
* the {@link GpgConfig} to use
|
35 |
-
* @return a {@link SignatureVerification} describing the outcome of the
|
36 |
-
* verification, or {@code null}Â if the object was not signed
|
37 |
-
* @throws IOException
|
38 |
-
* if an error occurs getting a public key
|
39 |
-
* @throws org.eclipse.jgit.api.errors.JGitInternalException
|
40 |
-
* if signature verification fails
|
41 |
-
*/
|
42 |
-
@Nullable
|
43 |
-
SignatureVerification verifySignature(@NonNull RevObject object,
|
44 |
-
@NonNull GpgConfig config) throws IOException;
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Verifies a given signature for given data.
|
48 |
-
*
|
49 |
-
* @param config
|
50 |
-
* the {@link GpgConfig}
|
51 |
-
* @param data
|
52 |
-
* the signature is for
|
53 |
-
* @param signatureData
|
54 |
-
* the ASCII-armored signature
|
55 |
-
* @return a {@link SignatureVerification} describing the outcome
|
56 |
-
* @throws IOException
|
57 |
-
* if the signature cannot be parsed
|
58 |
-
* @throws JGitInternalException
|
59 |
-
* if signature verification fails
|
60 |
-
* @since 6.9
|
61 |
-
*/
|
62 |
-
default SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
|
63 |
-
byte[] signatureData) throws IOException {
|
64 |
-
// Default implementation for backwards compatibility; override as
|
65 |
-
// appropriate
|
66 |
-
return verify(data, signatureData);
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Verifies a given signature for given data.
|
71 |
-
*
|
72 |
-
* @param data
|
73 |
-
* the signature is for
|
74 |
-
* @param signatureData
|
75 |
-
* the ASCII-armored signature
|
76 |
-
* @return a {@link SignatureVerification} describing the outcome
|
77 |
-
* @throws IOException
|
78 |
-
* if the signature cannot be parsed
|
79 |
-
* @throws JGitInternalException
|
80 |
-
* if signature verification fails
|
81 |
-
* @deprecated since 6.9, use {@link #verify(GpgConfig, byte[], byte[])}
|
82 |
-
* instead
|
83 |
-
*/
|
84 |
-
@Deprecated
|
85 |
-
public SignatureVerification verify(byte[] data, byte[] signatureData)
|
86 |
-
throws IOException;
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Retrieves the name of this verifier. This should be a short string
|
90 |
-
* identifying the engine that verified the signature, like "gpg" if GPG is
|
91 |
-
* used, or "bc" for a BouncyCastle implementation.
|
92 |
-
*
|
93 |
-
* @return the name
|
94 |
-
*/
|
95 |
-
@NonNull
|
96 |
-
String getName();
|
97 |
-
|
98 |
-
/**
|
99 |
-
* A {@link GpgSignatureVerifier} may cache public keys to speed up
|
100 |
-
* verifying signatures on multiple objects. This clears this cache, if any.
|
101 |
-
*/
|
102 |
-
void clear();
|
103 |
-
|
104 |
-
/**
|
105 |
-
* A {@code SignatureVerification} returns data about a (positively or
|
106 |
-
* negatively) verified signature.
|
107 |
-
*/
|
108 |
-
interface SignatureVerification {
|
109 |
-
|
110 |
-
// Data about the signature.
|
111 |
-
|
112 |
-
@NonNull
|
113 |
-
Date getCreationDate();
|
114 |
-
|
115 |
-
// Data from the signature used to find a public key.
|
116 |
-
|
117 |
-
/**
|
118 |
-
* Obtains the signer as stored in the signature, if known.
|
119 |
-
*
|
120 |
-
* @return the signer, or {@code null} if unknown
|
121 |
-
*/
|
122 |
-
String getSigner();
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Obtains the short or long fingerprint of the public key as stored in
|
126 |
-
* the signature, if known.
|
127 |
-
*
|
128 |
-
* @return the fingerprint, or {@code null} if unknown
|
129 |
-
*/
|
130 |
-
String getKeyFingerprint();
|
131 |
-
|
132 |
-
// Some information about the found public key.
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Obtains the OpenPGP user ID associated with the key.
|
136 |
-
*
|
137 |
-
* @return the user id, or {@code null} if unknown
|
138 |
-
*/
|
139 |
-
String getKeyUser();
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Tells whether the public key used for this signature verification was
|
143 |
-
* expired when the signature was created.
|
144 |
-
*
|
145 |
-
* @return {@code true} if the key was expired already, {@code false}
|
146 |
-
* otherwise
|
147 |
-
*/
|
148 |
-
boolean isExpired();
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Obtains the trust level of the public key used to verify the
|
152 |
-
* signature.
|
153 |
-
*
|
154 |
-
* @return the trust level
|
155 |
-
*/
|
156 |
-
@NonNull
|
157 |
-
TrustLevel getTrustLevel();
|
158 |
-
|
159 |
-
// The verification result.
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Tells whether the signature verification was successful.
|
163 |
-
*
|
164 |
-
* @return {@code true} if the signature was verified successfully;
|
165 |
-
* {@code false} if not.
|
166 |
-
*/
|
167 |
-
boolean getVerified();
|
168 |
-
|
169 |
-
/**
|
170 |
-
* Obtains a human-readable message giving additional information about
|
171 |
-
* the outcome of the verification.
|
172 |
-
*
|
173 |
-
* @return the message, or {@code null} if none set.
|
174 |
-
*/
|
175 |
-
String getMessage();
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* The owner's trust in a public key.
|
180 |
-
*/
|
181 |
-
enum TrustLevel {
|
182 |
-
UNKNOWN, NEVER, MARGINAL, FULL, ULTIMATE
|
183 |
-
}
|
184 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,92 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* Copyright (C) 2021, 2022 Thomas Wolf <thomas.wolf@paranor.ch> and others
|
3 |
-
*
|
4 |
-
* This program and the accompanying materials are made available under the
|
5 |
-
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
-
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
-
*
|
8 |
-
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
-
*/
|
10 |
-
package org.eclipse.jgit.lib;
|
11 |
-
|
12 |
-
import java.util.Iterator;
|
13 |
-
import java.util.ServiceConfigurationError;
|
14 |
-
import java.util.ServiceLoader;
|
15 |
-
|
16 |
-
import org.slf4j.Logger;
|
17 |
-
import org.slf4j.LoggerFactory;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* A {@code GpgSignatureVerifierFactory} creates {@link GpgSignatureVerifier} instances.
|
21 |
-
*
|
22 |
-
* @since 5.11
|
23 |
-
*/
|
24 |
-
public abstract class GpgSignatureVerifierFactory {
|
25 |
-
|
26 |
-
private static final Logger LOG = LoggerFactory
|
27 |
-
.getLogger(GpgSignatureVerifierFactory.class);
|
28 |
-
|
29 |
-
private static class DefaultFactory {
|
30 |
-
|
31 |
-
private static volatile GpgSignatureVerifierFactory defaultFactory = loadDefault();
|
32 |
-
|
33 |
-
private static GpgSignatureVerifierFactory loadDefault() {
|
34 |
-
try {
|
35 |
-
ServiceLoader<GpgSignatureVerifierFactory> loader = ServiceLoader
|
36 |
-
.load(GpgSignatureVerifierFactory.class);
|
37 |
-
Iterator<GpgSignatureVerifierFactory> iter = loader.iterator();
|
38 |
-
if (iter.hasNext()) {
|
39 |
-
return iter.next();
|
40 |
-
}
|
41 |
-
} catch (ServiceConfigurationError e) {
|
42 |
-
LOG.error(e.getMessage(), e);
|
43 |
-
}
|
44 |
-
return null;
|
45 |
-
}
|
46 |
-
|
47 |
-
private DefaultFactory() {
|
48 |
-
// No instantiation
|
49 |
-
}
|
50 |
-
|
51 |
-
public static GpgSignatureVerifierFactory getDefault() {
|
52 |
-
return defaultFactory;
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Sets the default factory.
|
57 |
-
*
|
58 |
-
* @param factory
|
59 |
-
* the new default factory
|
60 |
-
*/
|
61 |
-
public static void setDefault(GpgSignatureVerifierFactory factory) {
|
62 |
-
defaultFactory = factory;
|
63 |
-
}
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Retrieves the default factory.
|
68 |
-
*
|
69 |
-
* @return the default factory or {@code null} if none set
|
70 |
-
*/
|
71 |
-
public static GpgSignatureVerifierFactory getDefault() {
|
72 |
-
return DefaultFactory.getDefault();
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Sets the default factory.
|
77 |
-
*
|
78 |
-
* @param factory
|
79 |
-
* the new default factory
|
80 |
-
*/
|
81 |
-
public static void setDefault(GpgSignatureVerifierFactory factory) {
|
82 |
-
DefaultFactory.setDefault(factory);
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Creates a new {@link GpgSignatureVerifier}.
|
87 |
-
*
|
88 |
-
* @return the new {@link GpgSignatureVerifier}
|
89 |
-
*/
|
90 |
-
public abstract GpgSignatureVerifier getVerifier();
|
91 |
-
|
92 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,141 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* Copyright (C) 2018, 2022 Salesforce and others
|
3 |
-
*
|
4 |
-
* This program and the accompanying materials are made available under the
|
5 |
-
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
-
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
-
*
|
8 |
-
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
-
*/
|
10 |
-
package org.eclipse.jgit.lib;
|
11 |
-
|
12 |
-
import java.util.Iterator;
|
13 |
-
import java.util.ServiceConfigurationError;
|
14 |
-
import java.util.ServiceLoader;
|
15 |
-
|
16 |
-
import org.eclipse.jgit.annotations.NonNull;
|
17 |
-
import org.eclipse.jgit.annotations.Nullable;
|
18 |
-
import org.eclipse.jgit.api.errors.CanceledException;
|
19 |
-
import org.eclipse.jgit.transport.CredentialsProvider;
|
20 |
-
import org.slf4j.Logger;
|
21 |
-
import org.slf4j.LoggerFactory;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Creates GPG signatures for Git objects.
|
25 |
-
*
|
26 |
-
* @since 5.3
|
27 |
-
*/
|
28 |
-
public abstract class GpgSigner {
|
29 |
-
|
30 |
-
private static final Logger LOG = LoggerFactory.getLogger(GpgSigner.class);
|
31 |
-
|
32 |
-
private static class DefaultSigner {
|
33 |
-
|
34 |
-
private static volatile GpgSigner defaultSigner = loadGpgSigner();
|
35 |
-
|
36 |
-
private static GpgSigner loadGpgSigner() {
|
37 |
-
try {
|
38 |
-
ServiceLoader<GpgSigner> loader = ServiceLoader
|
39 |
-
.load(GpgSigner.class);
|
40 |
-
Iterator<GpgSigner> iter = loader.iterator();
|
41 |
-
if (iter.hasNext()) {
|
42 |
-
return iter.next();
|
43 |
-
}
|
44 |
-
} catch (ServiceConfigurationError e) {
|
45 |
-
LOG.error(e.getMessage(), e);
|
46 |
-
}
|
47 |
-
return null;
|
48 |
-
}
|
49 |
-
|
50 |
-
private DefaultSigner() {
|
51 |
-
// No instantiation
|
52 |
-
}
|
53 |
-
|
54 |
-
public static GpgSigner getDefault() {
|
55 |
-
return defaultSigner;
|
56 |
-
}
|
57 |
-
|
58 |
-
public static void setDefault(GpgSigner signer) {
|
59 |
-
defaultSigner = signer;
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Get the default signer, or <code>null</code>.
|
65 |
-
*
|
66 |
-
* @return the default signer, or <code>null</code>.
|
67 |
-
*/
|
68 |
-
public static GpgSigner getDefault() {
|
69 |
-
return DefaultSigner.getDefault();
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Set the default signer.
|
74 |
-
*
|
75 |
-
* @param signer
|
76 |
-
* the new default signer, may be <code>null</code> to select no
|
77 |
-
* default.
|
78 |
-
*/
|
79 |
-
public static void setDefault(GpgSigner signer) {
|
80 |
-
DefaultSigner.setDefault(signer);
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Signs the specified commit.
|
85 |
-
*
|
86 |
-
* <p>
|
87 |
-
* Implementors should obtain the payload for signing from the specified
|
88 |
-
* commit via {@link CommitBuilder#build()} and create a proper
|
89 |
-
* {@link GpgSignature}. The generated signature must be set on the
|
90 |
-
* specified {@code commit} (see
|
91 |
-
* {@link CommitBuilder#setGpgSignature(GpgSignature)}).
|
92 |
-
* </p>
|
93 |
-
* <p>
|
94 |
-
* Any existing signature on the commit must be discarded prior obtaining
|
95 |
-
* the payload via {@link CommitBuilder#build()}.
|
96 |
-
* </p>
|
97 |
-
*
|
98 |
-
* @param commit
|
99 |
-
* the commit to sign (must not be <code>null</code> and must be
|
100 |
-
* complete to allow proper calculation of payload)
|
101 |
-
* @param gpgSigningKey
|
102 |
-
* the signing key to locate (passed as is to the GPG signing
|
103 |
-
* tool as is; eg., value of <code>user.signingkey</code>)
|
104 |
-
* @param committer
|
105 |
-
* the signing identity (to help with key lookup in case signing
|
106 |
-
* key is not specified)
|
107 |
-
* @param credentialsProvider
|
108 |
-
* provider to use when querying for signing key credentials (eg.
|
109 |
-
* passphrase)
|
110 |
-
* @throws CanceledException
|
111 |
-
* when signing was canceled (eg., user aborted when entering
|
112 |
-
* passphrase)
|
113 |
-
*/
|
114 |
-
public abstract void sign(@NonNull CommitBuilder commit,
|
115 |
-
@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
|
116 |
-
CredentialsProvider credentialsProvider) throws CanceledException;
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Indicates if a signing key is available for the specified committer
|
120 |
-
* and/or signing key.
|
121 |
-
*
|
122 |
-
* @param gpgSigningKey
|
123 |
-
* the signing key to locate (passed as is to the GPG signing
|
124 |
-
* tool as is; eg., value of <code>user.signingkey</code>)
|
125 |
-
* @param committer
|
126 |
-
* the signing identity (to help with key lookup in case signing
|
127 |
-
* key is not specified)
|
128 |
-
* @param credentialsProvider
|
129 |
-
* provider to use when querying for signing key credentials (eg.
|
130 |
-
* passphrase)
|
131 |
-
* @return <code>true</code> if a signing key is available,
|
132 |
-
* <code>false</code> otherwise
|
133 |
-
* @throws CanceledException
|
134 |
-
* when signing was canceled (eg., user aborted when entering
|
135 |
-
* passphrase)
|
136 |
-
*/
|
137 |
-
public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey,
|
138 |
-
@NonNull PersonIdent committer,
|
139 |
-
CredentialsProvider credentialsProvider) throws CanceledException;
|
140 |
-
|
141 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -639,7 +639,7 @@ public boolean diff(ProgressMonitor monitor, int estWorkTreeSize,
|
|
639 |
// submodule repository in .git/modules doesn't
|
640 |
// exist yet it isn't "missing".
|
641 |
File gitDir = new File(
|
642 |
-
new File(repository.
|
643 |
Constants.MODULES),
|
644 |
subRepoPath);
|
645 |
if (!gitDir.isDirectory()) {
|
|
|
639 |
// submodule repository in .git/modules doesn't
|
640 |
// exist yet it isn't "missing".
|
641 |
File gitDir = new File(
|
642 |
+
new File(repository.getCommonDirectory(),
|
643 |
Constants.MODULES),
|
644 |
subRepoPath);
|
645 |
if (!gitDir.isDirectory()) {
|
@@ -15,6 +15,7 @@
|
|
15 |
import java.io.ObjectInputStream;
|
16 |
import java.io.ObjectOutputStream;
|
17 |
import java.io.Serializable;
|
|
|
18 |
|
19 |
import org.eclipse.jgit.annotations.Nullable;
|
20 |
import org.eclipse.jgit.errors.InvalidObjectIdException;
|
@@ -151,6 +152,22 @@ public static final ObjectId fromRaw(byte[] bs, int p) {
|
|
151 |
return new ObjectId(a, b, c, d, e);
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
/**
|
155 |
* Convert an ObjectId from raw binary representation.
|
156 |
*
|
|
|
15 |
import java.io.ObjectInputStream;
|
16 |
import java.io.ObjectOutputStream;
|
17 |
import java.io.Serializable;
|
18 |
+
import java.nio.ByteBuffer;
|
19 |
|
20 |
import org.eclipse.jgit.annotations.Nullable;
|
21 |
import org.eclipse.jgit.errors.InvalidObjectIdException;
|
|
|
152 |
return new ObjectId(a, b, c, d, e);
|
153 |
}
|
154 |
|
155 |
+
/**
|
156 |
+
* Convert an ObjectId from raw binary representation
|
157 |
+
*
|
158 |
+
* @param bb
|
159 |
+
* a bytebuffer with the objectid encoded as 5 consecutive ints.
|
160 |
+
* This is the reverse of {@link ObjectId#copyRawTo(ByteBuffer)}
|
161 |
+
*
|
162 |
+
* @return the converted object id.
|
163 |
+
*
|
164 |
+
* @since 7.0
|
165 |
+
*/
|
166 |
+
public static final ObjectId fromRaw(ByteBuffer bb) {
|
167 |
+
return new ObjectId(bb.getInt(), bb.getInt(), bb.getInt(), bb.getInt(),
|
168 |
+
bb.getInt());
|
169 |
+
}
|
170 |
+
|
171 |
/**
|
172 |
* Convert an ObjectId from raw binary representation.
|
173 |
*
|
@@ -237,23 +237,6 @@ public boolean performsAtomicTransactions() {
|
|
237 |
return false;
|
238 |
}
|
239 |
|
240 |
-
/**
|
241 |
-
* Compatibility synonym for {@link #findRef(String)}.
|
242 |
-
*
|
243 |
-
* @param name
|
244 |
-
* the name of the reference. May be a short name which must be
|
245 |
-
* searched for using the standard {@link #SEARCH_PATH}.
|
246 |
-
* @return the reference (if it exists); else {@code null}.
|
247 |
-
* @throws IOException
|
248 |
-
* the reference space cannot be accessed.
|
249 |
-
* @deprecated Use {@link #findRef(String)} instead.
|
250 |
-
*/
|
251 |
-
@Deprecated
|
252 |
-
@Nullable
|
253 |
-
public final Ref getRef(String name) throws IOException {
|
254 |
-
return findRef(name);
|
255 |
-
}
|
256 |
-
|
257 |
/**
|
258 |
* Read a single reference.
|
259 |
* <p>
|
|
|
237 |
return false;
|
238 |
}
|
239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
/**
|
241 |
* Read a single reference.
|
242 |
* <p>
|
@@ -113,9 +113,12 @@ public static ListenerList getGlobalListenerList() {
|
|
113 |
|
114 |
final AtomicLong closedAt = new AtomicLong();
|
115 |
|
116 |
-
/**
|
117 |
private final File gitDir;
|
118 |
|
|
|
|
|
|
|
119 |
/** File abstraction used to resolve paths. */
|
120 |
private final FS fs;
|
121 |
|
@@ -137,6 +140,7 @@ public static ListenerList getGlobalListenerList() {
|
|
137 |
*/
|
138 |
protected Repository(BaseRepositoryBuilder options) {
|
139 |
gitDir = options.getGitDir();
|
|
|
140 |
fs = options.getFS();
|
141 |
workTree = options.getWorkTree();
|
142 |
indexFile = options.getIndexFile();
|
@@ -219,6 +223,16 @@ public File getDirectory() {
|
|
219 |
*/
|
220 |
public abstract String getIdentifier();
|
221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
/**
|
223 |
* Get the object database which stores this repository's data.
|
224 |
*
|
@@ -292,25 +306,6 @@ public FS getFS() {
|
|
292 |
return fs;
|
293 |
}
|
294 |
|
295 |
-
/**
|
296 |
-
* Whether the specified object is stored in this repo or any of the known
|
297 |
-
* shared repositories.
|
298 |
-
*
|
299 |
-
* @param objectId
|
300 |
-
* a {@link org.eclipse.jgit.lib.AnyObjectId} object.
|
301 |
-
* @return true if the specified object is stored in this repo or any of the
|
302 |
-
* known shared repositories.
|
303 |
-
* @deprecated use {@code getObjectDatabase().has(objectId)}
|
304 |
-
*/
|
305 |
-
@Deprecated
|
306 |
-
public boolean hasObject(AnyObjectId objectId) {
|
307 |
-
try {
|
308 |
-
return getObjectDatabase().has(objectId);
|
309 |
-
} catch (IOException e) {
|
310 |
-
throw new UncheckedIOException(e);
|
311 |
-
}
|
312 |
-
}
|
313 |
-
|
314 |
/**
|
315 |
* Open an object from this repository.
|
316 |
* <p>
|
@@ -1150,11 +1145,9 @@ public Map<String, Ref> getTags() {
|
|
1150 |
* new Ref object representing the same data as Ref, but isPeeled()
|
1151 |
* will be true and getPeeledObjectId will contain the peeled object
|
1152 |
* (or null).
|
1153 |
-
* @deprecated use {@code getRefDatabase().peel(ref)} instead.
|
1154 |
*/
|
1155 |
-
@Deprecated
|
1156 |
@NonNull
|
1157 |
-
|
1158 |
try {
|
1159 |
return getRefDatabase().peel(ref);
|
1160 |
} catch (IOException e) {
|
|
|
113 |
|
114 |
final AtomicLong closedAt = new AtomicLong();
|
115 |
|
116 |
+
/** $GIT_DIR: metadata directory holding the repository's critical files. */
|
117 |
private final File gitDir;
|
118 |
|
119 |
+
/** $GIT_COMMON_DIR: metadata directory holding the common repository's critical files. */
|
120 |
+
private final File gitCommonDir;
|
121 |
+
|
122 |
/** File abstraction used to resolve paths. */
|
123 |
private final FS fs;
|
124 |
|
|
|
140 |
*/
|
141 |
protected Repository(BaseRepositoryBuilder options) {
|
142 |
gitDir = options.getGitDir();
|
143 |
+
gitCommonDir = options.getGitCommonDir();
|
144 |
fs = options.getFS();
|
145 |
workTree = options.getWorkTree();
|
146 |
indexFile = options.getIndexFile();
|
|
|
223 |
*/
|
224 |
public abstract String getIdentifier();
|
225 |
|
226 |
+
/**
|
227 |
+
* Get common dir.
|
228 |
+
*
|
229 |
+
* @return $GIT_COMMON_DIR: local common metadata directory;
|
230 |
+
* @since 7.0
|
231 |
+
*/
|
232 |
+
public File getCommonDirectory() {
|
233 |
+
return gitCommonDir;
|
234 |
+
}
|
235 |
+
|
236 |
/**
|
237 |
* Get the object database which stores this repository's data.
|
238 |
*
|
|
|
306 |
return fs;
|
307 |
}
|
308 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
309 |
/**
|
310 |
* Open an object from this repository.
|
311 |
* <p>
|
|
|
1145 |
* new Ref object representing the same data as Ref, but isPeeled()
|
1146 |
* will be true and getPeeledObjectId will contain the peeled object
|
1147 |
* (or null).
|
|
|
1148 |
*/
|
|
|
1149 |
@NonNull
|
1150 |
+
private Ref peel(Ref ref) {
|
1151 |
try {
|
1152 |
return getRefDatabase().peel(ref);
|
1153 |
} catch (IOException e) {
|
@@ -450,10 +450,21 @@ public String toString() {
|
|
450 |
* Git directory.
|
451 |
*/
|
452 |
public static boolean isGitRepository(File dir, FS fs) {
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
}
|
458 |
|
459 |
private static boolean isValidHead(File head) {
|
@@ -496,15 +507,31 @@ private static String readFirstLine(File head) {
|
|
496 |
* null if there is no suitable match.
|
497 |
*/
|
498 |
public static File resolve(File directory, FS fs) {
|
499 |
-
|
|
|
500 |
return directory;
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
508 |
return null;
|
509 |
}
|
510 |
}
|
|
|
450 |
* Git directory.
|
451 |
*/
|
452 |
public static boolean isGitRepository(File dir, FS fs) {
|
453 |
+
// check if common-dir available or fallback to git-dir
|
454 |
+
File commonDir;
|
455 |
+
try {
|
456 |
+
commonDir = fs.getCommonDir(dir);
|
457 |
+
} catch (IOException e) {
|
458 |
+
commonDir = null;
|
459 |
+
}
|
460 |
+
if (commonDir == null) {
|
461 |
+
commonDir = dir;
|
462 |
+
}
|
463 |
+
return fs.resolve(commonDir, Constants.OBJECTS).exists()
|
464 |
+
&& fs.resolve(commonDir, "refs").exists() //$NON-NLS-1$
|
465 |
+
&& (fs.resolve(commonDir, Constants.REFTABLE).exists()
|
466 |
+
|| isValidHead(
|
467 |
+
new File(commonDir, Constants.HEAD)));
|
468 |
}
|
469 |
|
470 |
private static boolean isValidHead(File head) {
|
|
|
507 |
* null if there is no suitable match.
|
508 |
*/
|
509 |
public static File resolve(File directory, FS fs) {
|
510 |
+
// the folder itself
|
511 |
+
if (isGitRepository(directory, fs)) {
|
512 |
return directory;
|
513 |
+
}
|
514 |
+
// the .git subfolder or file (reference)
|
515 |
+
File dotDir = new File(directory, Constants.DOT_GIT);
|
516 |
+
if (dotDir.isFile()) {
|
517 |
+
try {
|
518 |
+
File refDir = BaseRepositoryBuilder.getSymRef(directory,
|
519 |
+
dotDir, fs);
|
520 |
+
if (refDir != null && isGitRepository(refDir, fs)) {
|
521 |
+
return refDir;
|
522 |
+
}
|
523 |
+
} catch (IOException ignored) {
|
524 |
+
// Continue searching if gitdir ref isn't found
|
525 |
+
}
|
526 |
+
} else if (isGitRepository(dotDir, fs)) {
|
527 |
+
return dotDir;
|
528 |
+
}
|
529 |
+
// the folder extended with .git (bare)
|
530 |
+
File bareDir = new File(directory.getParentFile(),
|
531 |
+
directory.getName() + Constants.DOT_GIT_EXT);
|
532 |
+
if (isGitRepository(bareDir, fs)) {
|
533 |
+
return bareDir;
|
534 |
+
}
|
535 |
return null;
|
536 |
}
|
537 |
}
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
package org.eclipse.jgit.lib;
|
11 |
+
|
12 |
+
import java.io.IOException;
|
13 |
+
import java.util.Date;
|
14 |
+
|
15 |
+
import org.eclipse.jgit.annotations.NonNull;
|
16 |
+
import org.eclipse.jgit.api.errors.JGitInternalException;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* A {@code SignatureVerifier} can verify signatures on git commits and tags.
|
20 |
+
*
|
21 |
+
* @since 7.0
|
22 |
+
*/
|
23 |
+
public interface SignatureVerifier {
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Verifies a given signature for given data.
|
27 |
+
*
|
28 |
+
* @param repository
|
29 |
+
* the {@link Repository} the data comes from.
|
30 |
+
* @param config
|
31 |
+
* the {@link GpgConfig}
|
32 |
+
* @param data
|
33 |
+
* the signature is for
|
34 |
+
* @param signatureData
|
35 |
+
* the ASCII-armored signature
|
36 |
+
* @return a {@link SignatureVerification} describing the outcome
|
37 |
+
* @throws IOException
|
38 |
+
* if the signature cannot be parsed
|
39 |
+
* @throws JGitInternalException
|
40 |
+
* if signature verification fails
|
41 |
+
*/
|
42 |
+
SignatureVerification verify(@NonNull Repository repository,
|
43 |
+
@NonNull GpgConfig config, byte[] data, byte[] signatureData)
|
44 |
+
throws IOException;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Retrieves the name of this verifier. This should be a short string
|
48 |
+
* identifying the engine that verified the signature, like "gpg" if GPG is
|
49 |
+
* used, or "bc" for a BouncyCastle implementation.
|
50 |
+
*
|
51 |
+
* @return the name
|
52 |
+
*/
|
53 |
+
@NonNull
|
54 |
+
String getName();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* A {@link SignatureVerifier} may cache public keys to speed up
|
58 |
+
* verifying signatures on multiple objects. This clears this cache, if any.
|
59 |
+
*/
|
60 |
+
void clear();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* A {@code SignatureVerification} returns data about a (positively or
|
64 |
+
* negatively) verified signature.
|
65 |
+
*
|
66 |
+
* @param verifierName
|
67 |
+
* the name of the verifier that created this verification result
|
68 |
+
* @param creationDate
|
69 |
+
* date and time the signature was created
|
70 |
+
* @param signer
|
71 |
+
* the signer as stored in the signature, or {@code null} if
|
72 |
+
* unknown
|
73 |
+
* @param keyFingerprint
|
74 |
+
* fingerprint of the public key, or {@code null} if unknown
|
75 |
+
* @param keyUser
|
76 |
+
* user associated with the key, or {@code null} if unknown
|
77 |
+
* @param verified
|
78 |
+
* whether the signature verification was successful
|
79 |
+
* @param expired
|
80 |
+
* whether the public key used for this signature verification
|
81 |
+
* was expired when the signature was created
|
82 |
+
* @param trustLevel
|
83 |
+
* the trust level of the public key used to verify the signature
|
84 |
+
* @param message
|
85 |
+
* human-readable message giving additional information about the
|
86 |
+
* outcome of the verification, possibly {@code null}
|
87 |
+
*/
|
88 |
+
record SignatureVerification(
|
89 |
+
String verifierName,
|
90 |
+
Date creationDate,
|
91 |
+
String signer,
|
92 |
+
String keyFingerprint,
|
93 |
+
String keyUser,
|
94 |
+
boolean verified,
|
95 |
+
boolean expired,
|
96 |
+
@NonNull TrustLevel trustLevel,
|
97 |
+
String message) {
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* The owner's trust in a public key.
|
102 |
+
*/
|
103 |
+
enum TrustLevel {
|
104 |
+
UNKNOWN, NEVER, MARGINAL, FULL, ULTIMATE
|
105 |
+
}
|
106 |
+
}
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
package org.eclipse.jgit.lib;
|
11 |
+
|
12 |
+
import org.eclipse.jgit.annotations.NonNull;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* A factory for {@link SignatureVerifier}s.
|
16 |
+
*
|
17 |
+
* @since 7.0
|
18 |
+
*/
|
19 |
+
public interface SignatureVerifierFactory {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Tells what kind of {@link SignatureVerifier} this factory creates.
|
23 |
+
*
|
24 |
+
* @return the {@link GpgConfig.GpgFormat} of the signer
|
25 |
+
*/
|
26 |
+
@NonNull
|
27 |
+
GpgConfig.GpgFormat getType();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Creates a new instance of a {@link SignatureVerifier} that can produce
|
31 |
+
* signatures of type {@link #getType()}.
|
32 |
+
*
|
33 |
+
* @return a new {@link SignatureVerifier}
|
34 |
+
*/
|
35 |
+
@NonNull
|
36 |
+
SignatureVerifier create();
|
37 |
+
}
|
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
package org.eclipse.jgit.lib;
|
11 |
+
|
12 |
+
import java.io.IOException;
|
13 |
+
import java.nio.charset.StandardCharsets;
|
14 |
+
import java.text.MessageFormat;
|
15 |
+
import java.util.Arrays;
|
16 |
+
import java.util.EnumMap;
|
17 |
+
import java.util.Map;
|
18 |
+
import java.util.ServiceConfigurationError;
|
19 |
+
import java.util.ServiceLoader;
|
20 |
+
import java.util.concurrent.ConcurrentHashMap;
|
21 |
+
|
22 |
+
import org.eclipse.jgit.annotations.NonNull;
|
23 |
+
import org.eclipse.jgit.annotations.Nullable;
|
24 |
+
import org.eclipse.jgit.internal.JGitText;
|
25 |
+
import org.eclipse.jgit.revwalk.RevCommit;
|
26 |
+
import org.eclipse.jgit.revwalk.RevObject;
|
27 |
+
import org.eclipse.jgit.revwalk.RevTag;
|
28 |
+
import org.eclipse.jgit.util.RawParseUtils;
|
29 |
+
import org.slf4j.Logger;
|
30 |
+
import org.slf4j.LoggerFactory;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Manages the available signers.
|
34 |
+
*
|
35 |
+
* @since 7.0
|
36 |
+
*/
|
37 |
+
public final class SignatureVerifiers {
|
38 |
+
|
39 |
+
private static final Logger LOG = LoggerFactory.getLogger(SignatureVerifiers.class);
|
40 |
+
|
41 |
+
private static final byte[] PGP_PREFIX = Constants.GPG_SIGNATURE_PREFIX
|
42 |
+
.getBytes(StandardCharsets.US_ASCII);
|
43 |
+
|
44 |
+
private static final byte[] X509_PREFIX = Constants.CMS_SIGNATURE_PREFIX
|
45 |
+
.getBytes(StandardCharsets.US_ASCII);
|
46 |
+
|
47 |
+
private static final byte[] SSH_PREFIX = Constants.SSH_SIGNATURE_PREFIX
|
48 |
+
.getBytes(StandardCharsets.US_ASCII);
|
49 |
+
|
50 |
+
private static final Map<GpgConfig.GpgFormat, SignatureVerifierFactory> FACTORIES = loadSignatureVerifiers();
|
51 |
+
|
52 |
+
private static final Map<GpgConfig.GpgFormat, SignatureVerifier> VERIFIERS = new ConcurrentHashMap<>();
|
53 |
+
|
54 |
+
private static Map<GpgConfig.GpgFormat, SignatureVerifierFactory> loadSignatureVerifiers() {
|
55 |
+
Map<GpgConfig.GpgFormat, SignatureVerifierFactory> result = new EnumMap<>(
|
56 |
+
GpgConfig.GpgFormat.class);
|
57 |
+
try {
|
58 |
+
for (SignatureVerifierFactory factory : ServiceLoader
|
59 |
+
.load(SignatureVerifierFactory.class)) {
|
60 |
+
GpgConfig.GpgFormat format = factory.getType();
|
61 |
+
SignatureVerifierFactory existing = result.get(format);
|
62 |
+
if (existing != null) {
|
63 |
+
LOG.warn("{}", //$NON-NLS-1$
|
64 |
+
MessageFormat.format(
|
65 |
+
JGitText.get().signatureServiceConflict,
|
66 |
+
"SignatureVerifierFactory", format, //$NON-NLS-1$
|
67 |
+
existing.getClass().getCanonicalName(),
|
68 |
+
factory.getClass().getCanonicalName()));
|
69 |
+
} else {
|
70 |
+
result.put(format, factory);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
} catch (ServiceConfigurationError e) {
|
74 |
+
LOG.error(e.getMessage(), e);
|
75 |
+
}
|
76 |
+
return result;
|
77 |
+
}
|
78 |
+
|
79 |
+
private SignatureVerifiers() {
|
80 |
+
// No instantiation
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Retrieves a {@link Signer} that can produce signatures of the given type
|
85 |
+
* {@code format}.
|
86 |
+
*
|
87 |
+
* @param format
|
88 |
+
* {@link GpgConfig.GpgFormat} the signer must support
|
89 |
+
* @return a {@link Signer}, or {@code null} if none is available
|
90 |
+
*/
|
91 |
+
public static SignatureVerifier get(@NonNull GpgConfig.GpgFormat format) {
|
92 |
+
return VERIFIERS.computeIfAbsent(format, f -> {
|
93 |
+
SignatureVerifierFactory factory = FACTORIES.get(format);
|
94 |
+
if (factory == null) {
|
95 |
+
return null;
|
96 |
+
}
|
97 |
+
return factory.create();
|
98 |
+
});
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Sets a specific signature verifier to use for a specific signature type.
|
103 |
+
*
|
104 |
+
* @param format
|
105 |
+
* signature type to set the {@code verifier} for
|
106 |
+
* @param verifier
|
107 |
+
* the {@link SignatureVerifier} to use for signatures of type
|
108 |
+
* {@code format}; if {@code null}, a default implementation, if
|
109 |
+
* available, may be used.
|
110 |
+
*/
|
111 |
+
public static void set(@NonNull GpgConfig.GpgFormat format,
|
112 |
+
SignatureVerifier verifier) {
|
113 |
+
SignatureVerifier previous;
|
114 |
+
if (verifier == null) {
|
115 |
+
previous = VERIFIERS.remove(format);
|
116 |
+
} else {
|
117 |
+
previous = VERIFIERS.put(format, verifier);
|
118 |
+
}
|
119 |
+
if (previous != null) {
|
120 |
+
previous.clear();
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Verifies the signature on a signed commit or tag.
|
126 |
+
*
|
127 |
+
* @param repository
|
128 |
+
* the {@link Repository} the object is from
|
129 |
+
* @param config
|
130 |
+
* the {@link GpgConfig} to use
|
131 |
+
* @param object
|
132 |
+
* to verify
|
133 |
+
* @return a {@link SignatureVerifier.SignatureVerification} describing the
|
134 |
+
* outcome of the verification, or {@code null}Â if the object does
|
135 |
+
* not have a signature of a known type
|
136 |
+
* @throws IOException
|
137 |
+
* if an error occurs getting a public key
|
138 |
+
* @throws org.eclipse.jgit.api.errors.JGitInternalException
|
139 |
+
* if signature verification fails
|
140 |
+
*/
|
141 |
+
@Nullable
|
142 |
+
public static SignatureVerifier.SignatureVerification verify(
|
143 |
+
@NonNull Repository repository, @NonNull GpgConfig config,
|
144 |
+
@NonNull RevObject object) throws IOException {
|
145 |
+
if (object instanceof RevCommit) {
|
146 |
+
RevCommit commit = (RevCommit) object;
|
147 |
+
byte[] signatureData = commit.getRawGpgSignature();
|
148 |
+
if (signatureData == null) {
|
149 |
+
return null;
|
150 |
+
}
|
151 |
+
byte[] raw = commit.getRawBuffer();
|
152 |
+
// Now remove the GPG signature
|
153 |
+
byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
|
154 |
+
int start = RawParseUtils.headerStart(header, raw, 0);
|
155 |
+
if (start < 0) {
|
156 |
+
return null;
|
157 |
+
}
|
158 |
+
int end = RawParseUtils.nextLfSkippingSplitLines(raw, start);
|
159 |
+
// start is at the beginning of the header's content
|
160 |
+
start -= header.length + 1;
|
161 |
+
// end is on the terminating LF; we need to skip that, too
|
162 |
+
if (end < raw.length) {
|
163 |
+
end++;
|
164 |
+
}
|
165 |
+
byte[] data = new byte[raw.length - (end - start)];
|
166 |
+
System.arraycopy(raw, 0, data, 0, start);
|
167 |
+
System.arraycopy(raw, end, data, start, raw.length - end);
|
168 |
+
return verify(repository, config, data, signatureData);
|
169 |
+
} else if (object instanceof RevTag) {
|
170 |
+
RevTag tag = (RevTag) object;
|
171 |
+
byte[] signatureData = tag.getRawGpgSignature();
|
172 |
+
if (signatureData == null) {
|
173 |
+
return null;
|
174 |
+
}
|
175 |
+
byte[] raw = tag.getRawBuffer();
|
176 |
+
// The signature is just tacked onto the end of the message, which
|
177 |
+
// is last in the buffer.
|
178 |
+
byte[] data = Arrays.copyOfRange(raw, 0,
|
179 |
+
raw.length - signatureData.length);
|
180 |
+
return verify(repository, config, data, signatureData);
|
181 |
+
}
|
182 |
+
return null;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Verifies a given signature for some give data.
|
187 |
+
*
|
188 |
+
* @param repository
|
189 |
+
* the {@link Repository} the object is from
|
190 |
+
* @param config
|
191 |
+
* the {@link GpgConfig} to use
|
192 |
+
* @param data
|
193 |
+
* to verify the signature of
|
194 |
+
* @param signature
|
195 |
+
* the given signature of the {@code data}
|
196 |
+
* @return a {@link SignatureVerifier.SignatureVerification} describing the
|
197 |
+
* outcome of the verification, or {@code null}Â if the signature
|
198 |
+
* type is unknown
|
199 |
+
* @throws IOException
|
200 |
+
* if an error occurs getting a public key
|
201 |
+
* @throws org.eclipse.jgit.api.errors.JGitInternalException
|
202 |
+
* if signature verification fails
|
203 |
+
*/
|
204 |
+
@Nullable
|
205 |
+
public static SignatureVerifier.SignatureVerification verify(
|
206 |
+
@NonNull Repository repository, @NonNull GpgConfig config,
|
207 |
+
byte[] data, byte[] signature) throws IOException {
|
208 |
+
GpgConfig.GpgFormat format = getFormat(signature);
|
209 |
+
if (format == null) {
|
210 |
+
return null;
|
211 |
+
}
|
212 |
+
SignatureVerifier verifier = get(format);
|
213 |
+
if (verifier == null) {
|
214 |
+
return null;
|
215 |
+
}
|
216 |
+
return verifier.verify(repository, config, data, signature);
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Determines the type of a given signature.
|
221 |
+
*
|
222 |
+
* @param signature
|
223 |
+
* to get the type of
|
224 |
+
* @return the signature type, or {@code null} if unknown
|
225 |
+
*/
|
226 |
+
@Nullable
|
227 |
+
public static GpgConfig.GpgFormat getFormat(byte[] signature) {
|
228 |
+
if (RawParseUtils.match(signature, 0, PGP_PREFIX) > 0) {
|
229 |
+
return GpgConfig.GpgFormat.OPENPGP;
|
230 |
+
}
|
231 |
+
if (RawParseUtils.match(signature, 0, X509_PREFIX) > 0) {
|
232 |
+
return GpgConfig.GpgFormat.X509;
|
233 |
+
}
|
234 |
+
if (RawParseUtils.match(signature, 0, SSH_PREFIX) > 0) {
|
235 |
+
return GpgConfig.GpgFormat.SSH;
|
236 |
+
}
|
237 |
+
return null;
|
238 |
+
}
|
239 |
+
}
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
package org.eclipse.jgit.lib;
|
11 |
+
|
12 |
+
import java.io.IOException;
|
13 |
+
import java.io.UnsupportedEncodingException;
|
14 |
+
|
15 |
+
import org.eclipse.jgit.annotations.NonNull;
|
16 |
+
import org.eclipse.jgit.api.errors.CanceledException;
|
17 |
+
import org.eclipse.jgit.api.errors.JGitInternalException;
|
18 |
+
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
|
19 |
+
import org.eclipse.jgit.transport.CredentialsProvider;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Creates signatures for Git objects.
|
23 |
+
*
|
24 |
+
* @since 7.0
|
25 |
+
*/
|
26 |
+
public interface Signer {
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Signs the specified object.
|
30 |
+
*
|
31 |
+
* <p>
|
32 |
+
* Implementors should obtain the payload for signing from the specified
|
33 |
+
* object via {@link ObjectBuilder#build()} and create a proper
|
34 |
+
* {@link GpgSignature}. The generated signature is set on the specified
|
35 |
+
* {@code object} (see {@link ObjectBuilder#setGpgSignature(GpgSignature)}).
|
36 |
+
* </p>
|
37 |
+
* <p>
|
38 |
+
* Any existing signature on the object must be discarded prior obtaining
|
39 |
+
* the payload via {@link ObjectBuilder#build()}.
|
40 |
+
* </p>
|
41 |
+
*
|
42 |
+
* @param repository
|
43 |
+
* {@link Repository} the object belongs to
|
44 |
+
* @param config
|
45 |
+
* GPG settings from the git config
|
46 |
+
* @param object
|
47 |
+
* the object to sign (must not be {@code null} and must be
|
48 |
+
* complete to allow proper calculation of payload)
|
49 |
+
* @param committer
|
50 |
+
* the signing identity (to help with key lookup in case signing
|
51 |
+
* key is not specified)
|
52 |
+
* @param signingKey
|
53 |
+
* if non-{@code null} overrides the signing key from the config
|
54 |
+
* @param credentialsProvider
|
55 |
+
* provider to use when querying for signing key credentials (eg.
|
56 |
+
* passphrase)
|
57 |
+
* @throws CanceledException
|
58 |
+
* when signing was canceled (eg., user aborted when entering
|
59 |
+
* passphrase)
|
60 |
+
* @throws IOException
|
61 |
+
* if an I/O error occurs
|
62 |
+
* @throws UnsupportedSigningFormatException
|
63 |
+
* if a config is given and the wanted key format is not
|
64 |
+
* supported
|
65 |
+
*/
|
66 |
+
default void signObject(@NonNull Repository repository,
|
67 |
+
@NonNull GpgConfig config, @NonNull ObjectBuilder object,
|
68 |
+
@NonNull PersonIdent committer, String signingKey,
|
69 |
+
CredentialsProvider credentialsProvider)
|
70 |
+
throws CanceledException, IOException,
|
71 |
+
UnsupportedSigningFormatException {
|
72 |
+
try {
|
73 |
+
object.setGpgSignature(sign(repository, config, object.build(),
|
74 |
+
committer, signingKey, credentialsProvider));
|
75 |
+
} catch (UnsupportedEncodingException e) {
|
76 |
+
throw new JGitInternalException(e.getMessage(), e);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Signs arbitrary data.
|
82 |
+
*
|
83 |
+
* @param repository
|
84 |
+
* {@link Repository} the signature is created in
|
85 |
+
* @param config
|
86 |
+
* GPG settings from the git config
|
87 |
+
* @param data
|
88 |
+
* the data to sign
|
89 |
+
* @param committer
|
90 |
+
* the signing identity (to help with key lookup in case signing
|
91 |
+
* key is not specified)
|
92 |
+
* @param signingKey
|
93 |
+
* if non-{@code null} overrides the signing key from the config
|
94 |
+
* @param credentialsProvider
|
95 |
+
* provider to use when querying for signing key credentials (eg.
|
96 |
+
* passphrase)
|
97 |
+
* @return the signature for {@code data}
|
98 |
+
* @throws CanceledException
|
99 |
+
* when signing was canceled (eg., user aborted when entering
|
100 |
+
* passphrase)
|
101 |
+
* @throws IOException
|
102 |
+
* if an I/O error occurs
|
103 |
+
* @throws UnsupportedSigningFormatException
|
104 |
+
* if a config is given and the wanted key format is not
|
105 |
+
* supported
|
106 |
+
*/
|
107 |
+
GpgSignature sign(@NonNull Repository repository, @NonNull GpgConfig config,
|
108 |
+
byte[] data, @NonNull PersonIdent committer, String signingKey,
|
109 |
+
CredentialsProvider credentialsProvider) throws CanceledException,
|
110 |
+
IOException, UnsupportedSigningFormatException;
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Indicates if a signing key is available for the specified committer
|
114 |
+
* and/or signing key.
|
115 |
+
*
|
116 |
+
* @param repository
|
117 |
+
* the current {@link Repository}
|
118 |
+
* @param config
|
119 |
+
* GPG settings from the git config
|
120 |
+
* @param committer
|
121 |
+
* the signing identity (to help with key lookup in case signing
|
122 |
+
* key is not specified)
|
123 |
+
* @param signingKey
|
124 |
+
* if non-{@code null} overrides the signing key from the config
|
125 |
+
* @param credentialsProvider
|
126 |
+
* provider to use when querying for signing key credentials (eg.
|
127 |
+
* passphrase)
|
128 |
+
* @return {@code true} if a signing key is available, {@code false}
|
129 |
+
* otherwise
|
130 |
+
* @throws CanceledException
|
131 |
+
* when signing was canceled (eg., user aborted when entering
|
132 |
+
* passphrase)
|
133 |
+
*/
|
134 |
+
boolean canLocateSigningKey(@NonNull Repository repository,
|
135 |
+
@NonNull GpgConfig config, @NonNull PersonIdent committer,
|
136 |
+
String signingKey, CredentialsProvider credentialsProvider)
|
137 |
+
throws CanceledException;
|
138 |
+
|
139 |
+
}
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
package org.eclipse.jgit.lib;
|
11 |
+
|
12 |
+
import org.eclipse.jgit.annotations.NonNull;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* A factory for {@link Signer}s.
|
16 |
+
*
|
17 |
+
* @since 7.0
|
18 |
+
*/
|
19 |
+
public interface SignerFactory {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Tells what kind of {@link Signer} this factory creates.
|
23 |
+
*
|
24 |
+
* @return the {@link GpgConfig.GpgFormat} of the signer
|
25 |
+
*/
|
26 |
+
@NonNull
|
27 |
+
GpgConfig.GpgFormat getType();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Creates a new instance of a {@link Signer} that can produce signatures of
|
31 |
+
* type {@link #getType()}.
|
32 |
+
*
|
33 |
+
* @return a new {@link Signer}
|
34 |
+
*/
|
35 |
+
@NonNull
|
36 |
+
Signer create();
|
37 |
+
}
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
|
3 |
+
*
|
4 |
+
* This program and the accompanying materials are made available under the
|
5 |
+
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
6 |
+
* https://www.eclipse.org/org/documents/edl-v10.php.
|
7 |
+
*
|
8 |
+
* SPDX-License-Identifier: BSD-3-Clause
|
9 |
+
*/
|
10 |
+
package org.eclipse.jgit.lib;
|
11 |
+
|
12 |
+
import java.text.MessageFormat;
|
13 |
+
import java.util.EnumMap;
|
14 |
+
import java.util.Map;
|
15 |
+
import java.util.ServiceConfigurationError;
|
16 |
+
import java.util.ServiceLoader;
|
17 |
+
import java.util.concurrent.ConcurrentHashMap;
|
18 |
+
|
19 |
+
import org.eclipse.jgit.annotations.NonNull;
|
20 |
+
import org.eclipse.jgit.internal.JGitText;
|
21 |
+
import org.slf4j.Logger;
|
22 |
+
import org.slf4j.LoggerFactory;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Manages the available signers.
|
26 |
+
*
|
27 |
+
* @since 7.0
|
28 |
+
*/
|
29 |
+
public final class Signers {
|
30 |
+
|
31 |
+
private static final Logger LOG = LoggerFactory.getLogger(Signers.class);
|
32 |
+
|
33 |
+
private static final Map<GpgConfig.GpgFormat, SignerFactory> SIGNER_FACTORIES = loadSigners();
|
34 |
+
|
35 |
+
private static final Map<GpgConfig.GpgFormat, Signer> SIGNERS = new ConcurrentHashMap<>();
|
36 |
+
|
37 |
+
private static Map<GpgConfig.GpgFormat, SignerFactory> loadSigners() {
|
38 |
+
Map<GpgConfig.GpgFormat, SignerFactory> result = new EnumMap<>(
|
39 |
+
GpgConfig.GpgFormat.class);
|
40 |
+
try {
|
41 |
+
for (SignerFactory factory : ServiceLoader
|
42 |
+
.load(SignerFactory.class)) {
|
43 |
+
GpgConfig.GpgFormat format = factory.getType();
|
44 |
+
SignerFactory existing = result.get(format);
|
45 |
+
if (existing != null) {
|
46 |
+
LOG.warn("{}", //$NON-NLS-1$
|
47 |
+
MessageFormat.format(
|
48 |
+
JGitText.get().signatureServiceConflict,
|
49 |
+
"SignerFactory", format, //$NON-NLS-1$
|
50 |
+
existing.getClass().getCanonicalName(),
|
51 |
+
factory.getClass().getCanonicalName()));
|
52 |
+
} else {
|
53 |
+
result.put(format, factory);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
} catch (ServiceConfigurationError e) {
|
57 |
+
LOG.error(e.getMessage(), e);
|
58 |
+
}
|
59 |
+
return result;
|
60 |
+
}
|
61 |
+
|
62 |
+
private Signers() {
|
63 |
+
// No instantiation
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Retrieves a {@link Signer} that can produce signatures of the given type
|
68 |
+
* {@code format}.
|
69 |
+
*
|
70 |
+
* @param format
|
71 |
+
* {@link GpgConfig.GpgFormat} the signer must support
|
72 |
+
* @return a {@link Signer}, or {@code null} if none is available
|
73 |
+
*/
|
74 |
+
public static Signer get(@NonNull GpgConfig.GpgFormat format) {
|
75 |
+
return SIGNERS.computeIfAbsent(format, f -> {
|
76 |
+
SignerFactory factory = SIGNER_FACTORIES.get(format);
|
77 |
+
if (factory == null) {
|
78 |
+
return null;
|
79 |
+
}
|
80 |
+
return factory.create();
|
81 |
+
});
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Sets a specific signer to use for a specific signature type.
|
86 |
+
*
|
87 |
+
* @param format
|
88 |
+
* signature type to set the {@code signer} for
|
89 |
+
* @param signer
|
90 |
+
* the {@link Signer} to use for signatures of type
|
91 |
+
* {@code format}; if {@code null}, a default implementation, if
|
92 |
+
* available, may be used.
|
93 |
+
*/
|
94 |
+
public static void set(@NonNull GpgConfig.GpgFormat format, Signer signer) {
|
95 |
+
if (signer == null) {
|
96 |
+
SIGNERS.remove(format);
|
97 |
+
} else {
|
98 |
+
SIGNERS.put(format, signer);
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}
|
@@ -206,23 +206,6 @@ public byte[] build() throws UnsupportedEncodingException {
|
|
206 |
return os.toByteArray();
|
207 |
}
|
208 |
|
209 |
-
/**
|
210 |
-
* Format this builder's state as an annotated tag object.
|
211 |
-
*
|
212 |
-
* @return this object in the canonical annotated tag format, suitable for
|
213 |
-
* storage in a repository, or {@code null} if the tag cannot be
|
214 |
-
* encoded
|
215 |
-
* @deprecated since 5.11; use {@link #build()} instead
|
216 |
-
*/
|
217 |
-
@Deprecated
|
218 |
-
public byte[] toByteArray() {
|
219 |
-
try {
|
220 |
-
return build();
|
221 |
-
} catch (UnsupportedEncodingException e) {
|
222 |
-
return null;
|
223 |
-
}
|
224 |
-
}
|
225 |
-
|
226 |
@SuppressWarnings("nls")
|
227 |
@Override
|
228 |
public String toString() {
|
|
|
206 |
return os.toByteArray();
|
207 |
}
|
208 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
@SuppressWarnings("nls")
|
210 |
@Override
|
211 |
public String toString() {
|
@@ -22,37 +22,6 @@
|
|
22 |
* A class to convert merge results into a Git conformant textual presentation
|
23 |
*/
|
24 |
public class MergeFormatter {
|
25 |
-
/**
|
26 |
-
* Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
|
27 |
-
* objects in a Git conformant way. This method also assumes that the
|
28 |
-
* {@link org.eclipse.jgit.diff.RawText} objects being merged are line
|
29 |
-
* oriented files which use LF as delimiter. This method will also use LF to
|
30 |
-
* separate chunks and conflict metadata, therefore it fits only to texts
|
31 |
-
* that are LF-separated lines.
|
32 |
-
*
|
33 |
-
* @param out
|
34 |
-
* the output stream where to write the textual presentation
|
35 |
-
* @param res
|
36 |
-
* the merge result which should be presented
|
37 |
-
* @param seqName
|
38 |
-
* When a conflict is reported each conflicting range will get a
|
39 |
-
* name. This name is following the "<<<<<<<
|
40 |
-
* " or ">>>>>>> " conflict markers. The
|
41 |
-
* names for the sequences are given in this list
|
42 |
-
* @param charsetName
|
43 |
-
* the name of the character set used when writing conflict
|
44 |
-
* metadata
|
45 |
-
* @throws java.io.IOException
|
46 |
-
* if an IO error occurred
|
47 |
-
* @deprecated Use
|
48 |
-
* {@link #formatMerge(OutputStream, MergeResult, List, Charset)}
|
49 |
-
* instead.
|
50 |
-
*/
|
51 |
-
@Deprecated
|
52 |
-
public void formatMerge(OutputStream out, MergeResult<RawText> res,
|
53 |
-
List<String> seqName, String charsetName) throws IOException {
|
54 |
-
formatMerge(out, res, seqName, Charset.forName(charsetName));
|
55 |
-
}
|
56 |
|
57 |
/**
|
58 |
* Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
|
@@ -111,40 +80,6 @@ public void formatMergeDiff3(OutputStream out,
|
|
111 |
new MergeFormatterPass(out, res, seqName, charset, true).formatMerge();
|
112 |
}
|
113 |
|
114 |
-
/**
|
115 |
-
* Formats the results of a merge of exactly two
|
116 |
-
* {@link org.eclipse.jgit.diff.RawText} objects in a Git conformant way.
|
117 |
-
* This convenience method accepts the names for the three sequences (base
|
118 |
-
* and the two merged sequences) as explicit parameters and doesn't require
|
119 |
-
* the caller to specify a List
|
120 |
-
*
|
121 |
-
* @param out
|
122 |
-
* the {@link java.io.OutputStream} where to write the textual
|
123 |
-
* presentation
|
124 |
-
* @param res
|
125 |
-
* the merge result which should be presented
|
126 |
-
* @param baseName
|
127 |
-
* the name ranges from the base should get
|
128 |
-
* @param oursName
|
129 |
-
* the name ranges from ours should get
|
130 |
-
* @param theirsName
|
131 |
-
* the name ranges from theirs should get
|
132 |
-
* @param charsetName
|
133 |
-
* the name of the character set used when writing conflict
|
134 |
-
* metadata
|
135 |
-
* @throws java.io.IOException
|
136 |
-
* if an IO error occurred
|
137 |
-
* @deprecated use
|
138 |
-
* {@link #formatMerge(OutputStream, MergeResult, String, String, String, Charset)}
|
139 |
-
* instead.
|
140 |
-
*/
|
141 |
-
@Deprecated
|
142 |
-
public void formatMerge(OutputStream out, MergeResult res, String baseName,
|
143 |
-
String oursName, String theirsName, String charsetName) throws IOException {
|
144 |
-
formatMerge(out, res, baseName, oursName, theirsName,
|
145 |
-
Charset.forName(charsetName));
|
146 |
-
}
|
147 |
-
|
148 |
/**
|
149 |
* Formats the results of a merge of exactly two
|
150 |
* {@link org.eclipse.jgit.diff.RawText} objects in a Git conformant way.
|
|
|
22 |
* A class to convert merge results into a Git conformant textual presentation
|
23 |
*/
|
24 |
public class MergeFormatter {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
/**
|
27 |
* Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
|
|
|
80 |
new MergeFormatterPass(out, res, seqName, charset, true).formatMerge();
|
81 |
}
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
/**
|
84 |
* Formats the results of a merge of exactly two
|
85 |
* {@link org.eclipse.jgit.diff.RawText} objects in a Git conformant way.
|
@@ -91,24 +91,6 @@ public String format(List<Ref> refsToMerge, Ref target) {
|
|
91 |
return sb.toString();
|
92 |
}
|
93 |
|
94 |
-
/**
|
95 |
-
* Add section with conflicting paths to merge message. Lines are prefixed
|
96 |
-
* with a hash.
|
97 |
-
*
|
98 |
-
* @param message
|
99 |
-
* the original merge message
|
100 |
-
* @param conflictingPaths
|
101 |
-
* the paths with conflicts
|
102 |
-
* @return merge message with conflicting paths added
|
103 |
-
* @deprecated since 6.1; use
|
104 |
-
* {@link #formatWithConflicts(String, Iterable, char)} instead
|
105 |
-
*/
|
106 |
-
@Deprecated
|
107 |
-
public String formatWithConflicts(String message,
|
108 |
-
List<String> conflictingPaths) {
|
109 |
-
return formatWithConflicts(message, conflictingPaths, '#');
|
110 |
-
}
|
111 |
-
|
112 |
/**
|
113 |
* Add section with conflicting paths to merge message.
|
114 |
*
|
|
|
91 |
return sb.toString();
|
92 |
}
|
93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
/**
|
95 |
* Add section with conflicting paths to merge message.
|
96 |
*
|
@@ -41,7 +41,6 @@
|
|
41 |
|
42 |
import org.eclipse.jgit.annotations.Nullable;
|
43 |
import org.eclipse.jgit.api.errors.FilterFailedException;
|
44 |
-
import org.eclipse.jgit.api.errors.PatchFormatException;
|
45 |
import org.eclipse.jgit.attributes.Attribute;
|
46 |
import org.eclipse.jgit.attributes.Attributes;
|
47 |
import org.eclipse.jgit.attributes.FilterCommand;
|
@@ -287,32 +286,6 @@ private void addErrorWithGitConflict(String msg, String oldFileName,
|
|
287 |
}
|
288 |
}
|
289 |
|
290 |
-
/**
|
291 |
-
* Applies the given patch
|
292 |
-
*
|
293 |
-
* @param patchInput
|
294 |
-
* the patch to apply.
|
295 |
-
* @return the result of the patch
|
296 |
-
* @throws PatchFormatException
|
297 |
-
* if the patch cannot be parsed
|
298 |
-
* @throws IOException
|
299 |
-
* if the patch read fails
|
300 |
-
* @deprecated use {@link #applyPatch(Patch)} instead
|
301 |
-
*/
|
302 |
-
@Deprecated
|
303 |
-
public Result applyPatch(InputStream patchInput)
|
304 |
-
throws PatchFormatException, IOException {
|
305 |
-
Patch p = new Patch();
|
306 |
-
try (InputStream inStream = patchInput) {
|
307 |
-
p.parse(inStream);
|
308 |
-
|
309 |
-
if (!p.getErrors().isEmpty()) {
|
310 |
-
throw new PatchFormatException(p.getErrors());
|
311 |
-
}
|
312 |
-
}
|
313 |
-
return applyPatch(p);
|
314 |
-
}
|
315 |
-
|
316 |
/**
|
317 |
* Applies the given patch
|
318 |
*
|
|
|
41 |
|
42 |
import org.eclipse.jgit.annotations.Nullable;
|
43 |
import org.eclipse.jgit.api.errors.FilterFailedException;
|
|
|
44 |
import org.eclipse.jgit.attributes.Attribute;
|
45 |
import org.eclipse.jgit.attributes.Attributes;
|
46 |
import org.eclipse.jgit.attributes.FilterCommand;
|
|
|
286 |
}
|
287 |
}
|
288 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
/**
|
290 |
* Applies the given patch
|
291 |
*
|
@@ -43,7 +43,7 @@
|
|
43 |
* Tree and blob objects reachable from interesting commits are automatically
|
44 |
* scheduled for inclusion in the results of {@link #nextObject()}, returning
|
45 |
* each object exactly once. Objects are sorted and returned according to the
|
46 |
-
*
|
47 |
* Ordering can be affected by changing the
|
48 |
* {@link org.eclipse.jgit.revwalk.RevSort} used to order the commits that are
|
49 |
* returned first.
|
@@ -163,29 +163,6 @@ private ObjectWalk(ObjectReader or, boolean closeReader) {
|
|
163 |
pathBuf = new byte[256];
|
164 |
}
|
165 |
|
166 |
-
/**
|
167 |
-
* Create an object reachability checker that will use bitmaps if possible.
|
168 |
-
*
|
169 |
-
* This reachability checker accepts any object as target. For checks
|
170 |
-
* exclusively between commits, see
|
171 |
-
* {@link RevWalk#createReachabilityChecker()}.
|
172 |
-
*
|
173 |
-
* @return an object reachability checker, using bitmaps if possible.
|
174 |
-
*
|
175 |
-
* @throws IOException
|
176 |
-
* when the index fails to load.
|
177 |
-
*
|
178 |
-
* @since 5.8
|
179 |
-
* @deprecated use
|
180 |
-
* {@code ObjectReader#createObjectReachabilityChecker(ObjectWalk)}
|
181 |
-
* instead.
|
182 |
-
*/
|
183 |
-
@Deprecated
|
184 |
-
public final ObjectReachabilityChecker createObjectReachabilityChecker()
|
185 |
-
throws IOException {
|
186 |
-
return reader.createObjectReachabilityChecker(this);
|
187 |
-
}
|
188 |
-
|
189 |
/**
|
190 |
* Mark an object or commit to start graph traversal from.
|
191 |
* <p>
|
|
|
43 |
* Tree and blob objects reachable from interesting commits are automatically
|
44 |
* scheduled for inclusion in the results of {@link #nextObject()}, returning
|
45 |
* each object exactly once. Objects are sorted and returned according to the
|
46 |
+
* commits that reference them and the order they appear within a tree.
|
47 |
* Ordering can be affected by changing the
|
48 |
* {@link org.eclipse.jgit.revwalk.RevSort} used to order the commits that are
|
49 |
* returned first.
|
|
|
163 |
pathBuf = new byte[256];
|
164 |
}
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
/**
|
167 |
* Mark an object or commit to start graph traversal from.
|
168 |
* <p>
|
@@ -26,40 +26,6 @@
|
|
26 |
* @since 5.4
|
27 |
*/
|
28 |
public interface ReachabilityChecker {
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Check if all targets are reachable from the {@code starters} commits.
|
32 |
-
* <p>
|
33 |
-
* Caller should parse the objectIds (preferably with
|
34 |
-
* {@code walk.parseCommit()} and handle missing/incorrect type objects
|
35 |
-
* before calling this method.
|
36 |
-
*
|
37 |
-
* @param targets
|
38 |
-
* commits to reach.
|
39 |
-
* @param starters
|
40 |
-
* known starting points.
|
41 |
-
* @return An unreachable target if at least one of the targets is
|
42 |
-
* unreachable. An empty optional if all targets are reachable from
|
43 |
-
* the starters.
|
44 |
-
*
|
45 |
-
* @throws MissingObjectException
|
46 |
-
* if any of the incoming objects doesn't exist in the
|
47 |
-
* repository.
|
48 |
-
* @throws IncorrectObjectTypeException
|
49 |
-
* if any of the incoming objects is not a commit or a tag.
|
50 |
-
* @throws IOException
|
51 |
-
* if any of the underlying indexes or readers can not be
|
52 |
-
* opened.
|
53 |
-
*
|
54 |
-
* @deprecated see {{@link #areAllReachable(Collection, Stream)}
|
55 |
-
*/
|
56 |
-
@Deprecated
|
57 |
-
default Optional<RevCommit> areAllReachable(Collection<RevCommit> targets,
|
58 |
-
Collection<RevCommit> starters) throws MissingObjectException,
|
59 |
-
IncorrectObjectTypeException, IOException {
|
60 |
-
return areAllReachable(targets, starters.stream());
|
61 |
-
}
|
62 |
-
|
63 |
/**
|
64 |
* Check if all targets are reachable from the {@code starters} commits.
|
65 |
* <p>
|
|
|
26 |
* @since 5.4
|
27 |
*/
|
28 |
public interface ReachabilityChecker {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
/**
|
30 |
* Check if all targets are reachable from the {@code starters} commits.
|
31 |
* <p>
|
@@ -38,8 +38,17 @@
|
|
38 |
*/
|
39 |
public class RevTag extends RevObject {
|
40 |
|
41 |
-
private static final byte[]
|
42 |
-
.encodeASCII("-----BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
/**
|
45 |
* Parse an annotated tag from its canonical format.
|
@@ -208,20 +217,27 @@ private int getSignatureStart() {
|
|
208 |
return msgB;
|
209 |
}
|
210 |
// Find the last signature start and return the rest
|
211 |
-
int start = nextStart(
|
212 |
if (start < 0) {
|
213 |
return start;
|
214 |
}
|
215 |
int next = RawParseUtils.nextLF(raw, start);
|
216 |
while (next < raw.length) {
|
217 |
-
int newStart = nextStart(
|
218 |
if (newStart < 0) {
|
219 |
break;
|
220 |
}
|
221 |
start = newStart;
|
222 |
next = RawParseUtils.nextLF(raw, start);
|
223 |
}
|
224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
}
|
226 |
|
227 |
/**
|
|
|
38 |
*/
|
39 |
public class RevTag extends RevObject {
|
40 |
|
41 |
+
private static final byte[] SIGNATURE_START = Constants
|
42 |
+
.encodeASCII("-----BEGIN"); //$NON-NLS-1$
|
43 |
+
|
44 |
+
private static final byte[] GPG_SIGNATURE_START = Constants
|
45 |
+
.encodeASCII(Constants.GPG_SIGNATURE_PREFIX);
|
46 |
+
|
47 |
+
private static final byte[] CMS_SIGNATURE_START = Constants
|
48 |
+
.encodeASCII(Constants.CMS_SIGNATURE_PREFIX);
|
49 |
+
|
50 |
+
private static final byte[] SSH_SIGNATURE_START = Constants
|
51 |
+
.encodeASCII(Constants.SSH_SIGNATURE_PREFIX);
|
52 |
|
53 |
/**
|
54 |
* Parse an annotated tag from its canonical format.
|
|
|
217 |
return msgB;
|
218 |
}
|
219 |
// Find the last signature start and return the rest
|
220 |
+
int start = nextStart(SIGNATURE_START, raw, msgB);
|
221 |
if (start < 0) {
|
222 |
return start;
|
223 |
}
|
224 |
int next = RawParseUtils.nextLF(raw, start);
|
225 |
while (next < raw.length) {
|
226 |
+
int newStart = nextStart(SIGNATURE_START, raw, next);
|
227 |
if (newStart < 0) {
|
228 |
break;
|
229 |
}
|
230 |
start = newStart;
|
231 |
next = RawParseUtils.nextLF(raw, start);
|
232 |
}
|
233 |
+
// SIGNATURE_START is just a prefix. Check that it is one of the known
|
234 |
+
// full signature start tags.
|
235 |
+
if (RawParseUtils.match(raw, start, GPG_SIGNATURE_START) > 0
|
236 |
+
|| RawParseUtils.match(raw, start, CMS_SIGNATURE_START) > 0
|
237 |
+
|| RawParseUtils.match(raw, start, SSH_SIGNATURE_START) > 0) {
|
238 |
+
return start;
|
239 |
+
}
|
240 |
+
return -1;
|
241 |
}
|
242 |
|
243 |
/**
|
@@ -31,9 +31,9 @@
|
|
31 |
import org.eclipse.jgit.errors.MissingObjectException;
|
32 |
import org.eclipse.jgit.errors.RevWalkException;
|
33 |
import org.eclipse.jgit.internal.JGitText;
|
|
|
34 |
import org.eclipse.jgit.lib.AnyObjectId;
|
35 |
import org.eclipse.jgit.lib.AsyncObjectLoaderQueue;
|
36 |
-
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
|
37 |
import org.eclipse.jgit.lib.Constants;
|
38 |
import org.eclipse.jgit.lib.MutableObjectId;
|
39 |
import org.eclipse.jgit.lib.NullProgressMonitor;
|
@@ -278,23 +278,6 @@ public ObjectReader getObjectReader() {
|
|
278 |
return reader;
|
279 |
}
|
280 |
|
281 |
-
/**
|
282 |
-
* Get a reachability checker for commits over this revwalk.
|
283 |
-
*
|
284 |
-
* @return the most efficient reachability checker for this repository.
|
285 |
-
* @throws IOException
|
286 |
-
* if it cannot open any of the underlying indices.
|
287 |
-
*
|
288 |
-
* @since 5.4
|
289 |
-
* @deprecated use {@code ObjectReader#createReachabilityChecker(RevWalk)}
|
290 |
-
* instead.
|
291 |
-
*/
|
292 |
-
@Deprecated
|
293 |
-
public final ReachabilityChecker createReachabilityChecker()
|
294 |
-
throws IOException {
|
295 |
-
return reader.createReachabilityChecker(this);
|
296 |
-
}
|
297 |
-
|
298 |
/**
|
299 |
* {@inheritDoc}
|
300 |
* <p>
|
|
|
31 |
import org.eclipse.jgit.errors.MissingObjectException;
|
32 |
import org.eclipse.jgit.errors.RevWalkException;
|
33 |
import org.eclipse.jgit.internal.JGitText;
|
34 |
+
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
|
35 |
import org.eclipse.jgit.lib.AnyObjectId;
|
36 |
import org.eclipse.jgit.lib.AsyncObjectLoaderQueue;
|
|
|
37 |
import org.eclipse.jgit.lib.Constants;
|
38 |
import org.eclipse.jgit.lib.MutableObjectId;
|
39 |
import org.eclipse.jgit.lib.NullProgressMonitor;
|
|
|
278 |
return reader;
|
279 |
}
|
280 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
/**
|
282 |
* {@inheritDoc}
|
283 |
* <p>
|
@@ -22,27 +22,6 @@
|
|
22 |
*/
|
23 |
@MXBean
|
24 |
public interface WindowCacheStats {
|
25 |
-
/**
|
26 |
-
* Get number of open files
|
27 |
-
*
|
28 |
-
* @return the number of open files.
|
29 |
-
* @deprecated use {@link #getOpenFileCount()} instead
|
30 |
-
*/
|
31 |
-
@Deprecated
|
32 |
-
public static int getOpenFiles() {
|
33 |
-
return (int) WindowCache.getInstance().getStats().getOpenFileCount();
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Get number of open bytes
|
38 |
-
*
|
39 |
-
* @return the number of open bytes.
|
40 |
-
* @deprecated use {@link #getOpenByteCount()} instead
|
41 |
-
*/
|
42 |
-
@Deprecated
|
43 |
-
public static long getOpenBytes() {
|
44 |
-
return WindowCache.getInstance().getStats().getOpenByteCount();
|
45 |
-
}
|
46 |
|
47 |
/**
|
48 |
* Get cache statistics
|
|
|
22 |
*/
|
23 |
@MXBean
|
24 |
public interface WindowCacheStats {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
/**
|
27 |
* Get cache statistics
|
@@ -757,8 +757,10 @@ void list() throws IOException {
|
|
757 |
|
758 |
final XMLReader xr;
|
759 |
try {
|
760 |
-
|
761 |
-
.
|
|
|
|
|
762 |
} catch (SAXException | ParserConfigurationException e) {
|
763 |
throw new IOException(
|
764 |
JGitText.get().noXMLParserAvailable, e);
|
|
|
757 |
|
758 |
final XMLReader xr;
|
759 |
try {
|
760 |
+
SAXParserFactory saxParserFactory = SAXParserFactory
|
761 |
+
.newInstance();
|
762 |
+
saxParserFactory.setNamespaceAware(true);
|
763 |
+
xr = saxParserFactory.newSAXParser().getXMLReader();
|
764 |
} catch (SAXException | ParserConfigurationException e) {
|
765 |
throw new IOException(
|
766 |
JGitText.get().noXMLParserAvailable, e);
|
@@ -530,7 +530,7 @@ public PackLock parse(ProgressMonitor receiving, ProgressMonitor resolving)
|
|
530 |
receiving.beginTask(JGitText.get().receivingObjects,
|
531 |
(int) expectedObjectCount);
|
532 |
try {
|
533 |
-
for (
|
534 |
indexOneObject();
|
535 |
receiving.update(1);
|
536 |
if (receiving.isCancelled())
|
|
|
530 |
receiving.beginTask(JGitText.get().receivingObjects,
|
531 |
(int) expectedObjectCount);
|
532 |
try {
|
533 |
+
for (long done = 0; done < expectedObjectCount; done++) {
|
534 |
indexOneObject();
|
535 |
receiving.update(1);
|
536 |
if (receiving.isCancelled())
|
@@ -43,24 +43,13 @@ public class PacketLineIn {
|
|
43 |
|
44 |
/**
|
45 |
* Magic return from {@link #readString()} when a flush packet is found.
|
46 |
-
*
|
47 |
-
* @deprecated Callers should use {@link #isEnd(String)} to check if a
|
48 |
-
* string is the end marker, or
|
49 |
-
* {@link PacketLineIn#readStrings()} to iterate over all
|
50 |
-
* strings in the input stream until the marker is reached.
|
51 |
*/
|
52 |
-
|
53 |
-
public static final String END = new String(); /* must not string pool */
|
54 |
|
55 |
/**
|
56 |
* Magic return from {@link #readString()} when a delim packet is found.
|
57 |
-
*
|
58 |
-
* @since 5.0
|
59 |
-
* @deprecated Callers should use {@link #isDelimiter(String)} to check if a
|
60 |
-
* string is the delimiter.
|
61 |
*/
|
62 |
-
|
63 |
-
public static final String DELIM = new String(); /* must not string pool */
|
64 |
|
65 |
enum AckNackResult {
|
66 |
/** NAK */
|
|
|
43 |
|
44 |
/**
|
45 |
* Magic return from {@link #readString()} when a flush packet is found.
|
|
|
|
|
|
|
|
|
|
|
46 |
*/
|
47 |
+
private static final String END = new String(); /* must not string pool */
|
|
|
48 |
|
49 |
/**
|
50 |
* Magic return from {@link #readString()} when a delim packet is found.
|
|
|
|
|
|
|
|
|
51 |
*/
|
52 |
+
private static final String DELIM = new String(); /* must not string pool */
|
|
|
53 |
|
54 |
enum AckNackResult {
|
55 |
/** NAK */
|
@@ -88,52 +88,6 @@
|
|
88 |
* Implements the server side of a push connection, receiving objects.
|
89 |
*/
|
90 |
public class ReceivePack {
|
91 |
-
/**
|
92 |
-
* Data in the first line of a request, the line itself plus capabilities.
|
93 |
-
*
|
94 |
-
* @deprecated Use {@link FirstCommand} instead.
|
95 |
-
* @since 5.6
|
96 |
-
*/
|
97 |
-
@Deprecated
|
98 |
-
public static class FirstLine {
|
99 |
-
private final FirstCommand command;
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Parse the first line of a receive-pack request.
|
103 |
-
*
|
104 |
-
* @param line
|
105 |
-
* line from the client.
|
106 |
-
*/
|
107 |
-
public FirstLine(String line) {
|
108 |
-
command = FirstCommand.fromLine(line);
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Get non-capabilities part of the line
|
113 |
-
*
|
114 |
-
* @return non-capabilities part of the line.
|
115 |
-
*/
|
116 |
-
public String getLine() {
|
117 |
-
return command.getLine();
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Get capabilities parsed from the line
|
122 |
-
*
|
123 |
-
* @return capabilities parsed from the line.
|
124 |
-
*/
|
125 |
-
public Set<String> getCapabilities() {
|
126 |
-
Set<String> reconstructedCapabilites = new HashSet<>();
|
127 |
-
for (Map.Entry<String, String> e : command.getCapabilities()
|
128 |
-
.entrySet()) {
|
129 |
-
String cap = e.getValue() == null ? e.getKey()
|
130 |
-
: e.getKey() + "=" + e.getValue(); //$NON-NLS-1$
|
131 |
-
reconstructedCapabilites.add(cap);
|
132 |
-
}
|
133 |
-
|
134 |
-
return reconstructedCapabilites;
|
135 |
-
}
|
136 |
-
}
|
137 |
|
138 |
/** Database we write the stored objects into. */
|
139 |
private final Repository db;
|
@@ -2148,22 +2102,6 @@ public void setUnpackErrorHandler(UnpackErrorHandler unpackErrorHandler) {
|
|
2148 |
this.unpackErrorHandler = unpackErrorHandler;
|
2149 |
}
|
2150 |
|
2151 |
-
/**
|
2152 |
-
* Set whether this class will report command failures as warning messages
|
2153 |
-
* before sending the command results.
|
2154 |
-
*
|
2155 |
-
* @param echo
|
2156 |
-
* if true this class will report command failures as warning
|
2157 |
-
* messages before sending the command results. This is usually
|
2158 |
-
* not necessary, but may help buggy Git clients that discard the
|
2159 |
-
* errors when all branches fail.
|
2160 |
-
* @deprecated no widely used Git versions need this any more
|
2161 |
-
*/
|
2162 |
-
@Deprecated
|
2163 |
-
public void setEchoCommandFailures(boolean echo) {
|
2164 |
-
// No-op.
|
2165 |
-
}
|
2166 |
-
|
2167 |
/**
|
2168 |
* Get the client session-id
|
2169 |
*
|
|
|
88 |
* Implements the server side of a push connection, receiving objects.
|
89 |
*/
|
90 |
public class ReceivePack {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
/** Database we write the stored objects into. */
|
93 |
private final Repository db;
|
|
|
2102 |
this.unpackErrorHandler = unpackErrorHandler;
|
2103 |
}
|
2104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2105 |
/**
|
2106 |
* Get the client session-id
|
2107 |
*
|
@@ -178,7 +178,6 @@ public void setUseProtocolV2(boolean b) {
|
|
178 |
*
|
179 |
* This method must be invoked prior to any of the following:
|
180 |
* <ul>
|
181 |
-
* <li>{@link #send(Map)}</li>
|
182 |
* <li>{@link #send(Collection)}</li>
|
183 |
* </ul>
|
184 |
*
|
@@ -195,7 +194,6 @@ public void setDerefTags(boolean deref) {
|
|
195 |
* <p>
|
196 |
* This method must be invoked prior to any of the following:
|
197 |
* <ul>
|
198 |
-
* <li>{@link #send(Map)}</li>
|
199 |
* <li>{@link #send(Collection)}</li>
|
200 |
* <li>{@link #advertiseHave(AnyObjectId)}</li>
|
201 |
* </ul>
|
@@ -230,7 +228,6 @@ public void advertiseCapability(String name, String value) {
|
|
230 |
* <p>
|
231 |
* This method must be invoked prior to any of the following:
|
232 |
* <ul>
|
233 |
-
* <li>{@link #send(Map)}</li>
|
234 |
* <li>{@link #send(Collection)}</li>
|
235 |
* <li>{@link #advertiseHave(AnyObjectId)}</li>
|
236 |
* </ul>
|
@@ -249,24 +246,6 @@ public void addSymref(String from, String to) {
|
|
249 |
}
|
250 |
}
|
251 |
|
252 |
-
/**
|
253 |
-
* Format an advertisement for the supplied refs.
|
254 |
-
*
|
255 |
-
* @param refs
|
256 |
-
* zero or more refs to format for the client. The collection is
|
257 |
-
* sorted before display if necessary, and therefore may appear
|
258 |
-
* in any order.
|
259 |
-
* @return set of ObjectIds that were advertised to the client.
|
260 |
-
* @throws java.io.IOException
|
261 |
-
* the underlying output stream failed to write out an
|
262 |
-
* advertisement record.
|
263 |
-
* @deprecated use {@link #send(Collection)} instead.
|
264 |
-
*/
|
265 |
-
@Deprecated
|
266 |
-
public Set<ObjectId> send(Map<String, Ref> refs) throws IOException {
|
267 |
-
return send(refs.values());
|
268 |
-
}
|
269 |
-
|
270 |
/**
|
271 |
* Format an advertisement for the supplied refs.
|
272 |
*
|
|
|
178 |
*
|
179 |
* This method must be invoked prior to any of the following:
|
180 |
* <ul>
|
|
|
181 |
* <li>{@link #send(Collection)}</li>
|
182 |
* </ul>
|
183 |
*
|
|
|
194 |
* <p>
|
195 |
* This method must be invoked prior to any of the following:
|
196 |
* <ul>
|
|
|
197 |
* <li>{@link #send(Collection)}</li>
|
198 |
* <li>{@link #advertiseHave(AnyObjectId)}</li>
|
199 |
* </ul>
|
|
|
228 |
* <p>
|
229 |
* This method must be invoked prior to any of the following:
|
230 |
* <ul>
|
|
|
231 |
* <li>{@link #send(Collection)}</li>
|
232 |
* <li>{@link #advertiseHave(AnyObjectId)}</li>
|
233 |
* </ul>
|
|
|
246 |
}
|
247 |
}
|
248 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
/**
|
250 |
* Format an advertisement for the supplied refs.
|
251 |
*
|
@@ -1120,28 +1120,6 @@ public void setRemoveDeletedRefs(boolean remove) {
|
|
1120 |
removeDeletedRefs = remove;
|
1121 |
}
|
1122 |
|
1123 |
-
/**
|
1124 |
-
* @return the blob limit value set with {@link #setFilterBlobLimit} or
|
1125 |
-
* {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
|
1126 |
-
* was set
|
1127 |
-
* @since 5.0
|
1128 |
-
* @deprecated Use {@link #getFilterSpec()} instead
|
1129 |
-
*/
|
1130 |
-
@Deprecated
|
1131 |
-
public final long getFilterBlobLimit() {
|
1132 |
-
return filterSpec.getBlobLimit();
|
1133 |
-
}
|
1134 |
-
|
1135 |
-
/**
|
1136 |
-
* @param bytes exclude blobs of size greater than this
|
1137 |
-
* @since 5.0
|
1138 |
-
* @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
|
1139 |
-
*/
|
1140 |
-
@Deprecated
|
1141 |
-
public final void setFilterBlobLimit(long bytes) {
|
1142 |
-
setFilterSpec(FilterSpec.withBlobLimit(bytes));
|
1143 |
-
}
|
1144 |
-
|
1145 |
/**
|
1146 |
* Get filter spec
|
1147 |
*
|
|
|
1120 |
removeDeletedRefs = remove;
|
1121 |
}
|
1122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1123 |
/**
|
1124 |
* Get filter spec
|
1125 |
*
|
@@ -254,6 +254,12 @@ private ProcessBuilder createProcess(List<String> args,
|
|
254 |
pb.environment().put(Constants.GIT_DIR_KEY,
|
255 |
directory.getPath());
|
256 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
return pb;
|
258 |
}
|
259 |
|
|
|
254 |
pb.environment().put(Constants.GIT_DIR_KEY,
|
255 |
directory.getPath());
|
256 |
}
|
257 |
+
File commonDirectory = local != null ? local.getCommonDirectory()
|
258 |
+
: null;
|
259 |
+
if (commonDirectory != null) {
|
260 |
+
pb.environment().put(Constants.GIT_COMMON_DIR_KEY,
|
261 |
+
commonDirectory.getPath());
|
262 |
+
}
|
263 |
return pb;
|
264 |
}
|
265 |
|
@@ -225,6 +225,7 @@ private Process spawn(String cmd,
|
|
225 |
env.remove("GIT_CONFIG"); //$NON-NLS-1$
|
226 |
env.remove("GIT_CONFIG_PARAMETERS"); //$NON-NLS-1$
|
227 |
env.remove("GIT_DIR"); //$NON-NLS-1$
|
|
|
228 |
env.remove("GIT_WORK_TREE"); //$NON-NLS-1$
|
229 |
env.remove("GIT_GRAFT_FILE"); //$NON-NLS-1$
|
230 |
env.remove("GIT_INDEX_FILE"); //$NON-NLS-1$
|
|
|
225 |
env.remove("GIT_CONFIG"); //$NON-NLS-1$
|
226 |
env.remove("GIT_CONFIG_PARAMETERS"); //$NON-NLS-1$
|
227 |
env.remove("GIT_DIR"); //$NON-NLS-1$
|
228 |
+
env.remove("GIT_COMMON_DIR"); //$NON-NLS-1$
|
229 |
env.remove("GIT_WORK_TREE"); //$NON-NLS-1$
|
230 |
env.remove("GIT_GRAFT_FILE"); //$NON-NLS-1$
|
231 |
env.remove("GIT_INDEX_FILE"); //$NON-NLS-1$
|
@@ -30,11 +30,11 @@
|
|
30 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_DONE;
|
31 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
|
32 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
|
|
|
33 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SHALLOW;
|
34 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
|
35 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
|
36 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
|
37 |
-
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SESSION_ID;
|
38 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
|
39 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WAIT_FOR_DONE;
|
40 |
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ACK;
|
@@ -80,7 +80,6 @@
|
|
80 |
import org.eclipse.jgit.internal.JGitText;
|
81 |
import org.eclipse.jgit.internal.storage.pack.CachedPackUriProvider;
|
82 |
import org.eclipse.jgit.internal.storage.pack.PackWriter;
|
83 |
-
import org.eclipse.jgit.internal.transport.parser.FirstWant;
|
84 |
import org.eclipse.jgit.lib.Constants;
|
85 |
import org.eclipse.jgit.lib.NullProgressMonitor;
|
86 |
import org.eclipse.jgit.lib.ObjectId;
|
@@ -172,52 +171,6 @@ void checkWants(UploadPack up, List<ObjectId> wants)
|
|
172 |
throws PackProtocolException, IOException;
|
173 |
}
|
174 |
|
175 |
-
/**
|
176 |
-
* Data in the first line of a want-list, the line itself plus options.
|
177 |
-
*
|
178 |
-
* @deprecated Use {@link FirstWant} instead
|
179 |
-
*/
|
180 |
-
@Deprecated
|
181 |
-
public static class FirstLine {
|
182 |
-
|
183 |
-
private final FirstWant firstWant;
|
184 |
-
|
185 |
-
/**
|
186 |
-
* @param line
|
187 |
-
* line from the client.
|
188 |
-
*/
|
189 |
-
public FirstLine(String line) {
|
190 |
-
try {
|
191 |
-
firstWant = FirstWant.fromLine(line);
|
192 |
-
} catch (PackProtocolException e) {
|
193 |
-
throw new UncheckedIOException(e);
|
194 |
-
}
|
195 |
-
}
|
196 |
-
|
197 |
-
/**
|
198 |
-
* Get non-capabilities part of the line
|
199 |
-
*
|
200 |
-
* @return non-capabilities part of the line.
|
201 |
-
*/
|
202 |
-
public String getLine() {
|
203 |
-
return firstWant.getLine();
|
204 |
-
}
|
205 |
-
|
206 |
-
/**
|
207 |
-
* Get capabilities parsed from the line
|
208 |
-
*
|
209 |
-
* @return capabilities parsed from the line.
|
210 |
-
*/
|
211 |
-
public Set<String> getOptions() {
|
212 |
-
if (firstWant.getAgent() != null) {
|
213 |
-
Set<String> caps = new HashSet<>(firstWant.getCapabilities());
|
214 |
-
caps.add(OPTION_AGENT + '=' + firstWant.getAgent());
|
215 |
-
return caps;
|
216 |
-
}
|
217 |
-
return firstWant.getCapabilities();
|
218 |
-
}
|
219 |
-
}
|
220 |
-
|
221 |
/*
|
222 |
* {@link java.util.function.Consumer} doesn't allow throwing checked
|
223 |
* exceptions. Define our own to propagate IOExceptions.
|
@@ -1692,18 +1645,6 @@ public int getDepth() {
|
|
1692 |
return currentRequest.getDepth();
|
1693 |
}
|
1694 |
|
1695 |
-
/**
|
1696 |
-
* Deprecated synonym for {@code getFilterSpec().getBlobLimit()}.
|
1697 |
-
*
|
1698 |
-
* @return filter blob limit requested by the client, or -1 if no limit
|
1699 |
-
* @since 5.3
|
1700 |
-
* @deprecated Use {@link #getFilterSpec()} instead
|
1701 |
-
*/
|
1702 |
-
@Deprecated
|
1703 |
-
public final long getFilterBlobLimit() {
|
1704 |
-
return getFilterSpec().getBlobLimit();
|
1705 |
-
}
|
1706 |
-
|
1707 |
/**
|
1708 |
* Returns the filter spec for the current request. Valid only after
|
1709 |
* calling recvWants(). This may be a no-op filter spec, but it won't be
|
|
|
30 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_DONE;
|
31 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
|
32 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
|
33 |
+
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SESSION_ID;
|
34 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SHALLOW;
|
35 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
|
36 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
|
37 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
|
|
|
38 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
|
39 |
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WAIT_FOR_DONE;
|
40 |
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ACK;
|
|
|
80 |
import org.eclipse.jgit.internal.JGitText;
|
81 |
import org.eclipse.jgit.internal.storage.pack.CachedPackUriProvider;
|
82 |
import org.eclipse.jgit.internal.storage.pack.PackWriter;
|
|
|
83 |
import org.eclipse.jgit.lib.Constants;
|
84 |
import org.eclipse.jgit.lib.NullProgressMonitor;
|
85 |
import org.eclipse.jgit.lib.ObjectId;
|
|
|
171 |
throws PackProtocolException, IOException;
|
172 |
}
|
173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
/*
|
175 |
* {@link java.util.function.Consumer} doesn't allow throwing checked
|
176 |
* exceptions. Define our own to propagate IOExceptions.
|
|
|
1645 |
return currentRequest.getDepth();
|
1646 |
}
|
1647 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1648 |
/**
|
1649 |
* Returns the filter spec for the current request. Valid only after
|
1650 |
* calling recvWants(). This may be a no-op filter spec, but it won't be
|
@@ -10,10 +10,6 @@
|
|
10 |
|
11 |
package org.eclipse.jgit.transport;
|
12 |
|
13 |
-
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
|
14 |
-
|
15 |
-
import java.util.Set;
|
16 |
-
|
17 |
import org.eclipse.jgit.util.StringUtils;
|
18 |
|
19 |
/**
|
@@ -91,43 +87,6 @@ public static void set(String agent) {
|
|
91 |
userAgent = StringUtils.isEmptyOrNull(agent) ? null : clean(agent);
|
92 |
}
|
93 |
|
94 |
-
/**
|
95 |
-
*
|
96 |
-
* @param options
|
97 |
-
* options
|
98 |
-
* @param transportAgent
|
99 |
-
* name of transport agent
|
100 |
-
* @return The transport agent.
|
101 |
-
* @deprecated Capabilities with <key>=<value> shape are now
|
102 |
-
* parsed alongside other capabilities in the ReceivePack flow.
|
103 |
-
*/
|
104 |
-
@Deprecated
|
105 |
-
static String getAgent(Set<String> options, String transportAgent) {
|
106 |
-
if (options == null || options.isEmpty()) {
|
107 |
-
return transportAgent;
|
108 |
-
}
|
109 |
-
for (String o : options) {
|
110 |
-
if (o.startsWith(OPTION_AGENT)
|
111 |
-
&& o.length() > OPTION_AGENT.length()
|
112 |
-
&& o.charAt(OPTION_AGENT.length()) == '=') {
|
113 |
-
return o.substring(OPTION_AGENT.length() + 1);
|
114 |
-
}
|
115 |
-
}
|
116 |
-
return transportAgent;
|
117 |
-
}
|
118 |
-
|
119 |
-
/**
|
120 |
-
*
|
121 |
-
* @param options
|
122 |
-
* options
|
123 |
-
* @return True if the transport agent is set. False otherwise.
|
124 |
-
* @deprecated Capabilities with <key>=<value> shape are now
|
125 |
-
* parsed alongside other capabilities in the ReceivePack flow.
|
126 |
-
*/
|
127 |
-
@Deprecated
|
128 |
-
static boolean hasAgent(Set<String> options) {
|
129 |
-
return getAgent(options, null) != null;
|
130 |
-
}
|
131 |
|
132 |
private UserAgent() {
|
133 |
}
|
|
|
10 |
|
11 |
package org.eclipse.jgit.transport;
|
12 |
|
|
|
|
|
|
|
|
|
13 |
import org.eclipse.jgit.util.StringUtils;
|
14 |
|
15 |
/**
|
|
|
87 |
userAgent = StringUtils.isEmptyOrNull(agent) ? null : clean(agent);
|
88 |
}
|
89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
private UserAgent() {
|
92 |
}
|
@@ -371,12 +371,6 @@ public long getLength() {
|
|
371 |
return attributes.getLength();
|
372 |
}
|
373 |
|
374 |
-
@Override
|
375 |
-
@Deprecated
|
376 |
-
public long getLastModified() {
|
377 |
-
return attributes.getLastModifiedInstant().toEpochMilli();
|
378 |
-
}
|
379 |
-
|
380 |
/**
|
381 |
* @since 5.1.9
|
382 |
*/
|
|
|
371 |
return attributes.getLength();
|
372 |
}
|
373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
/**
|
375 |
* @since 5.1.9
|
376 |
*/
|
@@ -498,6 +498,8 @@ private InputStream filterClean(InputStream in)
|
|
498 |
filterProcessBuilder.directory(repository.getWorkTree());
|
499 |
filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
|
500 |
repository.getDirectory().getAbsolutePath());
|
|
|
|
|
501 |
ExecutionResult result;
|
502 |
try {
|
503 |
result = fs.execute(filterProcessBuilder, in);
|
@@ -617,18 +619,6 @@ public long getEntryContentLength() throws IOException {
|
|
617 |
return canonLen;
|
618 |
}
|
619 |
|
620 |
-
/**
|
621 |
-
* Get the last modified time of this entry.
|
622 |
-
*
|
623 |
-
* @return last modified time of this file, in milliseconds since the epoch
|
624 |
-
* (Jan 1, 1970 UTC).
|
625 |
-
* @deprecated use {@link #getEntryLastModifiedInstant()} instead
|
626 |
-
*/
|
627 |
-
@Deprecated
|
628 |
-
public long getEntryLastModified() {
|
629 |
-
return current().getLastModified();
|
630 |
-
}
|
631 |
-
|
632 |
/**
|
633 |
* Get the last modified time of this entry.
|
634 |
*
|
@@ -1220,21 +1210,6 @@ public String toString() {
|
|
1220 |
*/
|
1221 |
public abstract long getLength();
|
1222 |
|
1223 |
-
/**
|
1224 |
-
* Get the last modified time of this entry.
|
1225 |
-
* <p>
|
1226 |
-
* <b>Note: Efficient implementation required.</b>
|
1227 |
-
* <p>
|
1228 |
-
* The implementation of this method must be efficient. If a subclass
|
1229 |
-
* needs to compute the value they should cache the reference within an
|
1230 |
-
* instance member instead.
|
1231 |
-
*
|
1232 |
-
* @return time since the epoch (in ms) of the last change.
|
1233 |
-
* @deprecated use {@link #getLastModifiedInstant()} instead
|
1234 |
-
*/
|
1235 |
-
@Deprecated
|
1236 |
-
public abstract long getLastModified();
|
1237 |
-
|
1238 |
/**
|
1239 |
* Get the last modified time of this entry.
|
1240 |
* <p>
|
@@ -1332,7 +1307,7 @@ IgnoreNode load(IgnoreNode parent) throws IOException {
|
|
1332 |
|
1333 |
IgnoreNode infoExclude = new IgnoreNodeWithParent(
|
1334 |
coreExclude);
|
1335 |
-
File exclude = fs.resolve(repository.
|
1336 |
Constants.INFO_EXCLUDE);
|
1337 |
if (fs.exists(exclude)) {
|
1338 |
loadRulesFromFile(infoExclude, exclude);
|
|
|
498 |
filterProcessBuilder.directory(repository.getWorkTree());
|
499 |
filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
|
500 |
repository.getDirectory().getAbsolutePath());
|
501 |
+
filterProcessBuilder.environment().put(Constants.GIT_COMMON_DIR_KEY,
|
502 |
+
repository.getCommonDirectory().getAbsolutePath());
|
503 |
ExecutionResult result;
|
504 |
try {
|
505 |
result = fs.execute(filterProcessBuilder, in);
|
|
|
619 |
return canonLen;
|
620 |
}
|
621 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
622 |
/**
|
623 |
* Get the last modified time of this entry.
|
624 |
*
|
|
|
1210 |
*/
|
1211 |
public abstract long getLength();
|
1212 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1213 |
/**
|
1214 |
* Get the last modified time of this entry.
|
1215 |
* <p>
|
|
|
1307 |
|
1308 |
IgnoreNode infoExclude = new IgnoreNodeWithParent(
|
1309 |
coreExclude);
|
1310 |
+
File exclude = fs.resolve(repository.getCommonDirectory(),
|
1311 |
Constants.INFO_EXCLUDE);
|
1312 |
if (fs.exists(exclude)) {
|
1313 |
loadRulesFromFile(infoExclude, exclude);
|
@@ -897,21 +897,6 @@ public static FS detect() {
|
|
897 |
return detect(null);
|
898 |
}
|
899 |
|
900 |
-
/**
|
901 |
-
* Whether FileStore attributes should be determined asynchronously
|
902 |
-
*
|
903 |
-
* @param asynch
|
904 |
-
* whether FileStore attributes should be determined
|
905 |
-
* asynchronously. If false access to cached attributes may block
|
906 |
-
* for some seconds for the first call per FileStore
|
907 |
-
* @since 5.1.9
|
908 |
-
* @deprecated Use {@link FileStoreAttributes#setBackground} instead
|
909 |
-
*/
|
910 |
-
@Deprecated
|
911 |
-
public static void setAsyncFileStoreAttributes(boolean asynch) {
|
912 |
-
FileStoreAttributes.setBackground(asynch);
|
913 |
-
}
|
914 |
-
|
915 |
/**
|
916 |
* Auto-detect the appropriate file system abstraction, taking into account
|
917 |
* the presence of a Cygwin installation on the system. Using jgit in
|
@@ -1080,24 +1065,6 @@ private void detectSymlinkSupport() {
|
|
1080 |
*/
|
1081 |
public abstract boolean setExecute(File f, boolean canExec);
|
1082 |
|
1083 |
-
/**
|
1084 |
-
* Get the last modified time of a file system object. If the OS/JRE support
|
1085 |
-
* symbolic links, the modification time of the link is returned, rather
|
1086 |
-
* than that of the link target.
|
1087 |
-
*
|
1088 |
-
* @param f
|
1089 |
-
* a {@link java.io.File} object.
|
1090 |
-
* @return last modified time of f
|
1091 |
-
* @throws java.io.IOException
|
1092 |
-
* if an IO error occurred
|
1093 |
-
* @since 3.0
|
1094 |
-
* @deprecated use {@link #lastModifiedInstant(Path)} instead
|
1095 |
-
*/
|
1096 |
-
@Deprecated
|
1097 |
-
public long lastModified(File f) throws IOException {
|
1098 |
-
return FileUtils.lastModified(f);
|
1099 |
-
}
|
1100 |
-
|
1101 |
/**
|
1102 |
* Get the last modified time of a file system object. If the OS/JRE support
|
1103 |
* symbolic links, the modification time of the link is returned, rather
|
@@ -1126,25 +1093,6 @@ public Instant lastModifiedInstant(File f) {
|
|
1126 |
return FileUtils.lastModifiedInstant(f.toPath());
|
1127 |
}
|
1128 |
|
1129 |
-
/**
|
1130 |
-
* Set the last modified time of a file system object.
|
1131 |
-
* <p>
|
1132 |
-
* For symlinks it sets the modified time of the link target.
|
1133 |
-
*
|
1134 |
-
* @param f
|
1135 |
-
* a {@link java.io.File} object.
|
1136 |
-
* @param time
|
1137 |
-
* last modified time
|
1138 |
-
* @throws java.io.IOException
|
1139 |
-
* if an IO error occurred
|
1140 |
-
* @since 3.0
|
1141 |
-
* @deprecated use {@link #setLastModified(Path, Instant)} instead
|
1142 |
-
*/
|
1143 |
-
@Deprecated
|
1144 |
-
public void setLastModified(File f, long time) throws IOException {
|
1145 |
-
FileUtils.setLastModified(f, time);
|
1146 |
-
}
|
1147 |
-
|
1148 |
/**
|
1149 |
* Set the last modified time of a file system object.
|
1150 |
* <p>
|
@@ -1799,25 +1747,6 @@ public void createSymLink(File path, String target) throws IOException {
|
|
1799 |
FileUtils.createSymLink(path, target);
|
1800 |
}
|
1801 |
|
1802 |
-
/**
|
1803 |
-
* Create a new file. See {@link java.io.File#createNewFile()}. Subclasses
|
1804 |
-
* of this class may take care to provide a safe implementation for this
|
1805 |
-
* even if {@link #supportsAtomicCreateNewFile()} is <code>false</code>
|
1806 |
-
*
|
1807 |
-
* @param path
|
1808 |
-
* the file to be created
|
1809 |
-
* @return <code>true</code> if the file was created, <code>false</code> if
|
1810 |
-
* the file already existed
|
1811 |
-
* @throws java.io.IOException
|
1812 |
-
* if an IO error occurred
|
1813 |
-
* @deprecated use {@link #createNewFileAtomic(File)} instead
|
1814 |
-
* @since 4.5
|
1815 |
-
*/
|
1816 |
-
@Deprecated
|
1817 |
-
public boolean createNewFile(File path) throws IOException {
|
1818 |
-
return path.createNewFile();
|
1819 |
-
}
|
1820 |
-
|
1821 |
/**
|
1822 |
* A token representing a file created by
|
1823 |
* {@link #createNewFileAtomic(File)}. The token must be retained until the
|
@@ -2042,6 +1971,8 @@ protected ProcessResult internalRunHookIfPresent(Repository repository,
|
|
2042 |
environment.put(Constants.GIT_DIR_KEY,
|
2043 |
repository.getDirectory().getAbsolutePath());
|
2044 |
if (!repository.isBare()) {
|
|
|
|
|
2045 |
environment.put(Constants.GIT_WORK_TREE_KEY,
|
2046 |
repository.getWorkTree().getAbsolutePath());
|
2047 |
}
|
@@ -2137,7 +2068,7 @@ private File getRunDirectory(Repository repository,
|
|
2137 |
case "post-receive": //$NON-NLS-1$
|
2138 |
case "post-update": //$NON-NLS-1$
|
2139 |
case "push-to-checkout": //$NON-NLS-1$
|
2140 |
-
return repository.
|
2141 |
default:
|
2142 |
return repository.getWorkTree();
|
2143 |
}
|
@@ -2150,7 +2081,7 @@ private File getHooksDirectory(Repository repository) {
|
|
2150 |
if (hooksDir != null) {
|
2151 |
return new File(hooksDir);
|
2152 |
}
|
2153 |
-
File dir = repository.
|
2154 |
return dir == null ? null : new File(dir, Constants.HOOKS);
|
2155 |
}
|
2156 |
|
@@ -2423,19 +2354,6 @@ public long getCreationTime() {
|
|
2423 |
return creationTime;
|
2424 |
}
|
2425 |
|
2426 |
-
/**
|
2427 |
-
* Get the time when the file was last modified in milliseconds since
|
2428 |
-
* the epoch
|
2429 |
-
*
|
2430 |
-
* @return the time (milliseconds since 1970-01-01) when this object was
|
2431 |
-
* last modified
|
2432 |
-
* @deprecated use getLastModifiedInstant instead
|
2433 |
-
*/
|
2434 |
-
@Deprecated
|
2435 |
-
public long getLastModifiedTime() {
|
2436 |
-
return lastModifiedInstant.toEpochMilli();
|
2437 |
-
}
|
2438 |
-
|
2439 |
/**
|
2440 |
* Get the time when this object was last modified
|
2441 |
*
|
@@ -2577,6 +2495,33 @@ public String normalize(String name) {
|
|
2577 |
return name;
|
2578 |
}
|
2579 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2580 |
/**
|
2581 |
* This runnable will consume an input stream's content into an output
|
2582 |
* stream as soon as it gets available.
|
|
|
897 |
return detect(null);
|
898 |
}
|
899 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
900 |
/**
|
901 |
* Auto-detect the appropriate file system abstraction, taking into account
|
902 |
* the presence of a Cygwin installation on the system. Using jgit in
|
|
|
1065 |
*/
|
1066 |
public abstract boolean setExecute(File f, boolean canExec);
|
1067 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1068 |
/**
|
1069 |
* Get the last modified time of a file system object. If the OS/JRE support
|
1070 |
* symbolic links, the modification time of the link is returned, rather
|
|
|
1093 |
return FileUtils.lastModifiedInstant(f.toPath());
|
1094 |
}
|
1095 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1096 |
/**
|
1097 |
* Set the last modified time of a file system object.
|
1098 |
* <p>
|
|
|
1747 |
FileUtils.createSymLink(path, target);
|
1748 |
}
|
1749 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1750 |
/**
|
1751 |
* A token representing a file created by
|
1752 |
* {@link #createNewFileAtomic(File)}. The token must be retained until the
|
|
|
1971 |
environment.put(Constants.GIT_DIR_KEY,
|
1972 |
repository.getDirectory().getAbsolutePath());
|
1973 |
if (!repository.isBare()) {
|
1974 |
+
environment.put(Constants.GIT_COMMON_DIR_KEY,
|
1975 |
+
repository.getCommonDirectory().getAbsolutePath());
|
1976 |
environment.put(Constants.GIT_WORK_TREE_KEY,
|
1977 |
repository.getWorkTree().getAbsolutePath());
|
1978 |
}
|
|
|
2068 |
case "post-receive": //$NON-NLS-1$
|
2069 |
case "post-update": //$NON-NLS-1$
|
2070 |
case "push-to-checkout": //$NON-NLS-1$
|
2071 |
+
return repository.getCommonDirectory();
|
2072 |
default:
|
2073 |
return repository.getWorkTree();
|
2074 |
}
|
|
|
2081 |
if (hooksDir != null) {
|
2082 |
return new File(hooksDir);
|
2083 |
}
|
2084 |
+
File dir = repository.getCommonDirectory();
|
2085 |
return dir == null ? null : new File(dir, Constants.HOOKS);
|
2086 |
}
|
2087 |
|
|
|
2354 |
return creationTime;
|
2355 |
}
|
2356 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2357 |
/**
|
2358 |
* Get the time when this object was last modified
|
2359 |
*
|
|
|
2495 |
return name;
|
2496 |
}
|
2497 |
|
2498 |
+
/**
|
2499 |
+
* Get common dir path.
|
2500 |
+
*
|
2501 |
+
* @param dir
|
2502 |
+
* the .git folder
|
2503 |
+
* @return common dir path
|
2504 |
+
* @throws IOException
|
2505 |
+
* if commondir file can't be read
|
2506 |
+
*
|
2507 |
+
* @since 7.0
|
2508 |
+
*/
|
2509 |
+
public File getCommonDir(File dir) throws IOException {
|
2510 |
+
// first the GIT_COMMON_DIR is same as GIT_DIR
|
2511 |
+
File commonDir = dir;
|
2512 |
+
// now check if commondir file exists (e.g. worktree repository)
|
2513 |
+
File commonDirFile = new File(dir, Constants.COMMONDIR_FILE);
|
2514 |
+
if (commonDirFile.isFile()) {
|
2515 |
+
String commonDirPath = new String(IO.readFully(commonDirFile))
|
2516 |
+
.trim();
|
2517 |
+
commonDir = new File(commonDirPath);
|
2518 |
+
if (!commonDir.isAbsolute()) {
|
2519 |
+
commonDir = new File(dir, commonDirPath).getCanonicalFile();
|
2520 |
+
}
|
2521 |
+
}
|
2522 |
+
return commonDir;
|
2523 |
+
}
|
2524 |
+
|
2525 |
/**
|
2526 |
* This runnable will consume an input stream's content into an output
|
2527 |
* stream as soon as it gets available.
|
@@ -341,73 +341,6 @@ public boolean supportsAtomicCreateNewFile() {
|
|
341 |
return supportsAtomicFileCreation == AtomicFileCreation.SUPPORTED;
|
342 |
}
|
343 |
|
344 |
-
@Override
|
345 |
-
@SuppressWarnings("boxing")
|
346 |
-
/**
|
347 |
-
* {@inheritDoc}
|
348 |
-
* <p>
|
349 |
-
* An implementation of the File#createNewFile() semantics which works also
|
350 |
-
* on NFS. If the config option
|
351 |
-
* {@code core.supportsAtomicCreateNewFile = true} (which is the default)
|
352 |
-
* then simply File#createNewFile() is called.
|
353 |
-
*
|
354 |
-
* But if {@code core.supportsAtomicCreateNewFile = false} then after
|
355 |
-
* successful creation of the lock file a hard link to that lock file is
|
356 |
-
* created and the attribute nlink of the lock file is checked to be 2. If
|
357 |
-
* multiple clients manage to create the same lock file nlink would be
|
358 |
-
* greater than 2 showing the error.
|
359 |
-
*
|
360 |
-
* @see "https://www.time-travellers.org/shane/papers/NFS_considered_harmful.html"
|
361 |
-
*
|
362 |
-
* @deprecated use {@link FS_POSIX#createNewFileAtomic(File)} instead
|
363 |
-
* @since 4.5
|
364 |
-
*/
|
365 |
-
@Deprecated
|
366 |
-
public boolean createNewFile(File lock) throws IOException {
|
367 |
-
if (!lock.createNewFile()) {
|
368 |
-
return false;
|
369 |
-
}
|
370 |
-
if (supportsAtomicCreateNewFile()) {
|
371 |
-
return true;
|
372 |
-
}
|
373 |
-
Path lockPath = lock.toPath();
|
374 |
-
Path link = null;
|
375 |
-
FileStore store = null;
|
376 |
-
try {
|
377 |
-
store = Files.getFileStore(lockPath);
|
378 |
-
} catch (SecurityException e) {
|
379 |
-
return true;
|
380 |
-
}
|
381 |
-
try {
|
382 |
-
Boolean canLink = CAN_HARD_LINK.computeIfAbsent(store,
|
383 |
-
s -> Boolean.TRUE);
|
384 |
-
if (Boolean.FALSE.equals(canLink)) {
|
385 |
-
return true;
|
386 |
-
}
|
387 |
-
link = Files.createLink(
|
388 |
-
Paths.get(lock.getAbsolutePath() + ".lnk"), //$NON-NLS-1$
|
389 |
-
lockPath);
|
390 |
-
Integer nlink = (Integer) Files.getAttribute(lockPath,
|
391 |
-
"unix:nlink"); //$NON-NLS-1$
|
392 |
-
if (nlink > 2) {
|
393 |
-
LOG.warn(MessageFormat.format(
|
394 |
-
JGitText.get().failedAtomicFileCreation, lockPath,
|
395 |
-
nlink));
|
396 |
-
return false;
|
397 |
-
} else if (nlink < 2) {
|
398 |
-
CAN_HARD_LINK.put(store, Boolean.FALSE);
|
399 |
-
}
|
400 |
-
return true;
|
401 |
-
} catch (UnsupportedOperationException | IllegalArgumentException e) {
|
402 |
-
CAN_HARD_LINK.put(store, Boolean.FALSE);
|
403 |
-
return true;
|
404 |
-
} finally {
|
405 |
-
if (link != null) {
|
406 |
-
Files.delete(link);
|
407 |
-
}
|
408 |
-
}
|
409 |
-
}
|
410 |
-
|
411 |
/**
|
412 |
* {@inheritDoc}
|
413 |
* <p>
|
|
|
341 |
return supportsAtomicFileCreation == AtomicFileCreation.SUPPORTED;
|
342 |
}
|
343 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
/**
|
345 |
* {@inheritDoc}
|
346 |
* <p>
|
@@ -770,24 +770,6 @@ static boolean isSymlink(File file) {
|
|
770 |
return Files.isSymbolicLink(file.toPath());
|
771 |
}
|
772 |
|
773 |
-
/**
|
774 |
-
* Get the lastModified attribute for a given file
|
775 |
-
*
|
776 |
-
* @param file
|
777 |
-
* the file
|
778 |
-
* @return lastModified attribute for given file, not following symbolic
|
779 |
-
* links
|
780 |
-
* @throws IOException
|
781 |
-
* if an IO error occurred
|
782 |
-
* @deprecated use {@link #lastModifiedInstant(Path)} instead which returns
|
783 |
-
* FileTime
|
784 |
-
*/
|
785 |
-
@Deprecated
|
786 |
-
static long lastModified(File file) throws IOException {
|
787 |
-
return Files.getLastModifiedTime(toPath(file), LinkOption.NOFOLLOW_LINKS)
|
788 |
-
.toMillis();
|
789 |
-
}
|
790 |
-
|
791 |
/**
|
792 |
* Get last modified timestamp of a file
|
793 |
*
|
@@ -827,21 +809,6 @@ static BasicFileAttributes fileAttributes(File file) throws IOException {
|
|
827 |
return Files.readAttributes(file.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
|
828 |
}
|
829 |
|
830 |
-
/**
|
831 |
-
* Set the last modified time of a file system object.
|
832 |
-
*
|
833 |
-
* @param file
|
834 |
-
* the file
|
835 |
-
* @param time
|
836 |
-
* last modified timestamp
|
837 |
-
* @throws IOException
|
838 |
-
* if an IO error occurred
|
839 |
-
*/
|
840 |
-
@Deprecated
|
841 |
-
static void setLastModified(File file, long time) throws IOException {
|
842 |
-
Files.setLastModifiedTime(toPath(file), FileTime.fromMillis(time));
|
843 |
-
}
|
844 |
-
|
845 |
/**
|
846 |
* Set the last modified time of a file system object.
|
847 |
*
|
|
|
770 |
return Files.isSymbolicLink(file.toPath());
|
771 |
}
|
772 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
773 |
/**
|
774 |
* Get last modified timestamp of a file
|
775 |
*
|
|
|
809 |
return Files.readAttributes(file.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
|
810 |
}
|
811 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
812 |
/**
|
813 |
* Set the last modified time of a file system object.
|
814 |
*
|
@@ -44,14 +44,6 @@
|
|
44 |
* Handy utility functions to parse raw object contents.
|
45 |
*/
|
46 |
public final class RawParseUtils {
|
47 |
-
/**
|
48 |
-
* UTF-8 charset constant.
|
49 |
-
*
|
50 |
-
* @since 2.2
|
51 |
-
* @deprecated use {@link java.nio.charset.StandardCharsets#UTF_8} instead
|
52 |
-
*/
|
53 |
-
@Deprecated
|
54 |
-
public static final Charset UTF8_CHARSET = UTF_8;
|
55 |
|
56 |
private static final byte[] digits10;
|
57 |
|
|
|
44 |
* Handy utility functions to parse raw object contents.
|
45 |
*/
|
46 |
public final class RawParseUtils {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
private static final byte[] digits10;
|
49 |
|
@@ -13,8 +13,8 @@
|
|
13 |
import java.util.Locale;
|
14 |
|
15 |
import org.eclipse.jgit.internal.JGitText;
|
16 |
-
import org.eclipse.jgit.lib.
|
17 |
-
import org.eclipse.jgit.lib.
|
18 |
import org.eclipse.jgit.lib.PersonIdent;
|
19 |
|
20 |
/**
|
@@ -39,29 +39,31 @@ private SignatureUtils() {
|
|
39 |
* to use for dates
|
40 |
* @return a textual representation of the {@link SignatureVerification},
|
41 |
* using LF as line separator
|
|
|
|
|
42 |
*/
|
43 |
public static String toString(SignatureVerification verification,
|
44 |
PersonIdent creator, GitDateFormatter formatter) {
|
45 |
StringBuilder result = new StringBuilder();
|
46 |
// Use the creator's timezone for the signature date
|
47 |
PersonIdent dateId = new PersonIdent(creator,
|
48 |
-
verification.
|
49 |
result.append(MessageFormat.format(JGitText.get().verifySignatureMade,
|
50 |
formatter.formatDate(dateId)));
|
51 |
result.append('\n');
|
52 |
result.append(MessageFormat.format(
|
53 |
JGitText.get().verifySignatureKey,
|
54 |
-
verification.
|
55 |
result.append('\n');
|
56 |
-
if (!StringUtils.isEmptyOrNull(verification.
|
57 |
result.append(
|
58 |
MessageFormat.format(JGitText.get().verifySignatureIssuer,
|
59 |
-
verification.
|
60 |
result.append('\n');
|
61 |
}
|
62 |
String msg;
|
63 |
-
if (verification.
|
64 |
-
if (verification.
|
65 |
msg = JGitText.get().verifySignatureExpired;
|
66 |
} else {
|
67 |
msg = JGitText.get().verifySignatureGood;
|
@@ -69,14 +71,14 @@ public static String toString(SignatureVerification verification,
|
|
69 |
} else {
|
70 |
msg = JGitText.get().verifySignatureBad;
|
71 |
}
|
72 |
-
result.append(MessageFormat.format(msg, verification.
|
73 |
-
if (!TrustLevel.UNKNOWN.equals(verification.
|
74 |
result.append(' ' + MessageFormat
|
75 |
.format(JGitText.get().verifySignatureTrust, verification
|
76 |
-
.
|
77 |
}
|
78 |
result.append('\n');
|
79 |
-
msg = verification.
|
80 |
if (!StringUtils.isEmptyOrNull(msg)) {
|
81 |
result.append(msg);
|
82 |
result.append('\n');
|
|
|
13 |
import java.util.Locale;
|
14 |
|
15 |
import org.eclipse.jgit.internal.JGitText;
|
16 |
+
import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
|
17 |
+
import org.eclipse.jgit.lib.SignatureVerifier.TrustLevel;
|
18 |
import org.eclipse.jgit.lib.PersonIdent;
|
19 |
|
20 |
/**
|
|
|
39 |
* to use for dates
|
40 |
* @return a textual representation of the {@link SignatureVerification},
|
41 |
* using LF as line separator
|
42 |
+
*
|
43 |
+
* @since 7.0
|
44 |
*/
|
45 |
public static String toString(SignatureVerification verification,
|
46 |
PersonIdent creator, GitDateFormatter formatter) {
|
47 |
StringBuilder result = new StringBuilder();
|
48 |
// Use the creator's timezone for the signature date
|
49 |
PersonIdent dateId = new PersonIdent(creator,
|
50 |
+
verification.creationDate());
|
51 |
result.append(MessageFormat.format(JGitText.get().verifySignatureMade,
|
52 |
formatter.formatDate(dateId)));
|
53 |
result.append('\n');
|
54 |
result.append(MessageFormat.format(
|
55 |
JGitText.get().verifySignatureKey,
|
56 |
+
verification.keyFingerprint().toUpperCase(Locale.ROOT)));
|
57 |
result.append('\n');
|
58 |
+
if (!StringUtils.isEmptyOrNull(verification.signer())) {
|
59 |
result.append(
|
60 |
MessageFormat.format(JGitText.get().verifySignatureIssuer,
|
61 |
+
verification.signer()));
|
62 |
result.append('\n');
|
63 |
}
|
64 |
String msg;
|
65 |
+
if (verification.verified()) {
|
66 |
+
if (verification.expired()) {
|
67 |
msg = JGitText.get().verifySignatureExpired;
|
68 |
} else {
|
69 |
msg = JGitText.get().verifySignatureGood;
|
|
|
71 |
} else {
|
72 |
msg = JGitText.get().verifySignatureBad;
|
73 |
}
|
74 |
+
result.append(MessageFormat.format(msg, verification.keyUser()));
|
75 |
+
if (!TrustLevel.UNKNOWN.equals(verification.trustLevel())) {
|
76 |
result.append(' ' + MessageFormat
|
77 |
.format(JGitText.get().verifySignatureTrust, verification
|
78 |
+
.trustLevel().name().toLowerCase(Locale.ROOT)));
|
79 |
}
|
80 |
result.append('\n');
|
81 |
+
msg = verification.message();
|
82 |
if (!StringUtils.isEmptyOrNull(msg)) {
|
83 |
result.append(msg);
|
84 |
result.append('\n');
|
@@ -147,44 +147,6 @@ public AutoLFInputStream(InputStream in, Set<StreamFlag> flags) {
|
|
147 |
&& flags.contains(StreamFlag.FOR_CHECKOUT);
|
148 |
}
|
149 |
|
150 |
-
/**
|
151 |
-
* Creates a new InputStream, wrapping the specified stream.
|
152 |
-
*
|
153 |
-
* @param in
|
154 |
-
* raw input stream
|
155 |
-
* @param detectBinary
|
156 |
-
* whether binaries should be detected
|
157 |
-
* @since 2.0
|
158 |
-
* @deprecated since 5.9, use {@link #create(InputStream, StreamFlag...)}
|
159 |
-
* instead
|
160 |
-
*/
|
161 |
-
@Deprecated
|
162 |
-
public AutoLFInputStream(InputStream in, boolean detectBinary) {
|
163 |
-
this(in, detectBinary, false);
|
164 |
-
}
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Creates a new InputStream, wrapping the specified stream.
|
168 |
-
*
|
169 |
-
* @param in
|
170 |
-
* raw input stream
|
171 |
-
* @param detectBinary
|
172 |
-
* whether binaries should be detected
|
173 |
-
* @param abortIfBinary
|
174 |
-
* throw an IOException if the file is binary
|
175 |
-
* @since 3.3
|
176 |
-
* @deprecated since 5.9, use {@link #create(InputStream, StreamFlag...)}
|
177 |
-
* instead
|
178 |
-
*/
|
179 |
-
@Deprecated
|
180 |
-
public AutoLFInputStream(InputStream in, boolean detectBinary,
|
181 |
-
boolean abortIfBinary) {
|
182 |
-
this.in = in;
|
183 |
-
this.detectBinary = detectBinary;
|
184 |
-
this.abortIfBinary = abortIfBinary;
|
185 |
-
this.forCheckout = false;
|
186 |
-
}
|
187 |
-
|
188 |
@Override
|
189 |
public int read() throws IOException {
|
190 |
final int read = read(single, 0, 1);
|
|
|
147 |
&& flags.contains(StreamFlag.FOR_CHECKOUT);
|
148 |
}
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
@Override
|
151 |
public int read() throws IOException {
|
152 |
final int read = read(single, 0, 1);
|