* stable-5.1: Prepare 5.1.12-SNAPSHOT builds JGit v5.1.11.201909031202-r Prepare 4.11.10-SNAPSHOT builds JGit v4.11.9.201909030838-r Bazel: Update bazlets to the latest master revision Bazel: Remove FileTreeIteratorWithTimeControl from BUILD file BatchRefUpdate: repro racy atomic update, and fix it Delete unused FileTreeIteratorWithTimeControl Fix RacyGitTests#testRacyGitDetection Change RacyGitTests to create a racy git situation in a stable way Silence API warnings Change-Id: Iac5dc9683cea97db04d20f27c10f2e103d3ae7b5 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v5.3.5.201909031855-r
@@ -15,7 +15,7 @@ versions.check(minimum_bazel_version = "0.19.0") | |||
load("//tools:bazlets.bzl", "load_bazlets") | |||
load_bazlets(commit = "8528a0df69dadf6311d8d3f81c1b693afda8bcf1") | |||
load_bazlets(commit = "09a035e98077dce549d5f6a7472d06c4b8f792d2") | |||
load( | |||
"@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl", |
@@ -1,13 +1,5 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<component id="org.eclipse.jgit.lfs.server" version="2"> | |||
<resource path="META-INF/MANIFEST.MF"> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="5.2.3"/> | |||
<message_argument value="5.2.0"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java" type="org.eclipse.jgit.lfs.server.fs.ObjectUploadListener"> | |||
<filter id="1142947843"> | |||
<message_arguments> |
@@ -1,11 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<component id="org.eclipse.jgit.lfs" version="2"> | |||
<resource path="META-INF/MANIFEST.MF"> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="5.2.3"/> | |||
<message_argument value="5.2.0"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
</component> |
@@ -43,6 +43,7 @@ | |||
package org.eclipse.jgit.internal.storage.file; | |||
import static java.nio.charset.StandardCharsets.UTF_8; | |||
import static java.util.concurrent.TimeUnit.NANOSECONDS; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
import static org.eclipse.jgit.internal.storage.file.BatchRefUpdateTest.Result.LOCK_FAILURE; | |||
@@ -64,6 +65,7 @@ import static org.junit.Assume.assumeTrue; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.file.Files; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
@@ -161,6 +163,33 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase { | |||
refsChangedEvents = 0; | |||
} | |||
@Test | |||
public void packedRefsFileIsSorted() throws IOException { | |||
assumeTrue(atomic); | |||
for (int i = 0; i < 2; i++) { | |||
BatchRefUpdate bu = diskRepo.getRefDatabase().newBatchUpdate(); | |||
String b1 = String.format("refs/heads/a%d",i); | |||
String b2 = String.format("refs/heads/b%d",i); | |||
bu.setAtomic(atomic); | |||
ReceiveCommand c1 = new ReceiveCommand(ObjectId.zeroId(), A, b1); | |||
ReceiveCommand c2 = new ReceiveCommand(ObjectId.zeroId(), B, b2); | |||
bu.addCommand(c1, c2); | |||
try (RevWalk rw = new RevWalk(diskRepo)) { | |||
bu.execute(rw, NullProgressMonitor.INSTANCE); | |||
} | |||
assertEquals(c1.getResult(), ReceiveCommand.Result.OK); | |||
assertEquals(c2.getResult(), ReceiveCommand.Result.OK); | |||
} | |||
File packed = new File(diskRepo.getDirectory(), "packed-refs"); | |||
String packedStr = new String(Files.readAllBytes(packed.toPath()), UTF_8); | |||
int a2 = packedStr.indexOf("refs/heads/a1"); | |||
int b1 = packedStr.indexOf("refs/heads/b0"); | |||
assertTrue(a2 < b1); | |||
} | |||
@Test | |||
public void simpleNoForce() throws IOException { | |||
writeLooseRef("refs/heads/master", A); |
@@ -1,13 +1,5 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<component id="org.eclipse.jgit" version="2"> | |||
<resource path="META-INF/MANIFEST.MF"> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="5.2.3"/> | |||
<message_argument value="5.2.0"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/dircache/DirCacheEntry.java" type="org.eclipse.jgit.dircache.DirCacheEntry"> | |||
<filter id="1142947843"> | |||
<message_arguments> | |||
@@ -42,6 +34,28 @@ | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/gitrepo/RepoCommand.java" type="org.eclipse.jgit.gitrepo.RepoCommand$DefaultRemoteReader"> | |||
<filter id="338792546"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.gitrepo.RepoCommand.DefaultRemoteReader"/> | |||
<message_argument value="readFile(String, String, String)"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="338792546"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.gitrepo.RepoCommand.DefaultRemoteReader"/> | |||
<message_argument value="readFileFromRepo(Repository, String, String)"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/gitrepo/RepoCommand.java" type="org.eclipse.jgit.gitrepo.RepoCommand$RemoteReader"> | |||
<filter id="403804204"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.gitrepo.RepoCommand.RemoteReader"/> | |||
<message_argument value="readFileWithMode(String, String, String)"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants"> | |||
<filter id="1142947843"> | |||
<message_arguments> | |||
@@ -62,6 +76,42 @@ | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lib/GitmoduleEntry.java" type="org.eclipse.jgit.lib.GitmoduleEntry"> | |||
<filter id="1109393411"> | |||
<message_arguments> | |||
<message_argument value="4.7.5"/> | |||
<message_argument value="org.eclipse.jgit.lib.GitmoduleEntry"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lib/ObjectChecker.java" type="org.eclipse.jgit.lib.ObjectChecker"> | |||
<filter id="1142947843"> | |||
<message_arguments> | |||
<message_argument value="4.7.5"/> | |||
<message_argument value="getGitsubmodules()"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/revwalk/DepthWalk.java" type="org.eclipse.jgit.revwalk.DepthWalk"> | |||
<filter id="403804204"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.revwalk.DepthWalk"/> | |||
<message_argument value="getDeepenNotFlag()"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="404000815"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.revwalk.DepthWalk"/> | |||
<message_argument value="getDeepenNots()"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="404000815"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.revwalk.DepthWalk"/> | |||
<message_argument value="getDeepenSince()"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/storage/pack/PackConfig.java" type="org.eclipse.jgit.storage.pack.PackConfig"> | |||
<filter id="336658481"> | |||
<message_arguments> | |||
@@ -118,6 +168,14 @@ | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/transport/RemoteSession.java" type="org.eclipse.jgit.transport.RemoteSession"> | |||
<filter id="404000815"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.RemoteSession"/> | |||
<message_argument value="getFtpChannel()"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/transport/TransferConfig.java" type="org.eclipse.jgit.transport.TransferConfig"> | |||
<filter id="1159725059"> | |||
<message_arguments> | |||
@@ -132,6 +190,14 @@ | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/transport/http/HttpConnection.java" type="org.eclipse.jgit.transport.http.HttpConnection"> | |||
<filter id="403804204"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.http.HttpConnection"/> | |||
<message_argument value="getHeaderFields(String)"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator"> | |||
<filter id="1142947843"> | |||
<message_arguments> |
@@ -51,10 +51,10 @@ import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_RE | |||
import java.io.IOException; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
@@ -364,65 +364,72 @@ class PackedBatchRefUpdate extends BatchRefUpdate { | |||
private static RefList<Ref> applyUpdates(RevWalk walk, RefList<Ref> refs, | |||
List<ReceiveCommand> commands) throws IOException { | |||
int nDeletes = 0; | |||
List<ReceiveCommand> adds = new ArrayList<>(commands.size()); | |||
// Construct a new RefList by merging the old list with the updates. | |||
// This assumes that each ref occurs at most once as a ReceiveCommand. | |||
Collections.sort(commands, new Comparator<ReceiveCommand>() { | |||
@Override | |||
public int compare(ReceiveCommand a, ReceiveCommand b) { | |||
return a.getRefName().compareTo(b.getRefName()); | |||
} | |||
}); | |||
int delta = 0; | |||
for (ReceiveCommand c : commands) { | |||
if (c.getType() == ReceiveCommand.Type.CREATE) { | |||
adds.add(c); | |||
} else if (c.getType() == ReceiveCommand.Type.DELETE) { | |||
nDeletes++; | |||
switch (c.getType()) { | |||
case DELETE: | |||
delta--; | |||
break; | |||
case CREATE: | |||
delta++; | |||
break; | |||
default: | |||
} | |||
} | |||
int addIdx = 0; | |||
// Construct a new RefList by linearly scanning the old list, and merging in | |||
// any updates. | |||
Map<String, ReceiveCommand> byName = byName(commands); | |||
RefList.Builder<Ref> b = | |||
new RefList.Builder<>(refs.size() - nDeletes + adds.size()); | |||
for (Ref ref : refs) { | |||
String name = ref.getName(); | |||
ReceiveCommand cmd = byName.remove(name); | |||
if (cmd == null) { | |||
b.add(ref); | |||
continue; | |||
} | |||
if (!cmd.getOldId().equals(ref.getObjectId())) { | |||
lockFailure(cmd, commands); | |||
return null; | |||
RefList.Builder<Ref> b = new RefList.Builder<>(refs.size() + delta); | |||
int refIdx = 0; | |||
int cmdIdx = 0; | |||
while (refIdx < refs.size() || cmdIdx < commands.size()) { | |||
Ref ref = (refIdx < refs.size()) ? refs.get(refIdx) : null; | |||
ReceiveCommand cmd = (cmdIdx < commands.size()) | |||
? commands.get(cmdIdx) | |||
: null; | |||
int cmp = 0; | |||
if (ref != null && cmd != null) { | |||
cmp = ref.getName().compareTo(cmd.getRefName()); | |||
} else if (ref == null) { | |||
cmp = 1; | |||
} else if (cmd == null) { | |||
cmp = -1; | |||
} | |||
// Consume any adds between the last and current ref. | |||
while (addIdx < adds.size()) { | |||
ReceiveCommand currAdd = adds.get(addIdx); | |||
if (currAdd.getRefName().compareTo(name) < 0) { | |||
b.add(peeledRef(walk, currAdd)); | |||
byName.remove(currAdd.getRefName()); | |||
} else { | |||
break; | |||
if (cmp < 0) { | |||
b.add(ref); | |||
refIdx++; | |||
} else if (cmp > 0) { | |||
assert cmd != null; | |||
if (cmd.getType() != ReceiveCommand.Type.CREATE) { | |||
lockFailure(cmd, commands); | |||
return null; | |||
} | |||
addIdx++; | |||
} | |||
if (cmd.getType() != ReceiveCommand.Type.DELETE) { | |||
b.add(peeledRef(walk, cmd)); | |||
} | |||
} | |||
// All remaining adds are valid, since the refs didn't exist. | |||
while (addIdx < adds.size()) { | |||
ReceiveCommand cmd = adds.get(addIdx++); | |||
byName.remove(cmd.getRefName()); | |||
b.add(peeledRef(walk, cmd)); | |||
} | |||
cmdIdx++; | |||
} else { | |||
assert cmd != null; | |||
assert ref != null; | |||
if (!cmd.getOldId().equals(ref.getObjectId())) { | |||
lockFailure(cmd, commands); | |||
return null; | |||
} | |||
// Any remaining updates/deletes do not correspond to any existing refs, so | |||
// they are lock failures. | |||
if (!byName.isEmpty()) { | |||
lockFailure(byName.values().iterator().next(), commands); | |||
return null; | |||
if (cmd.getType() != ReceiveCommand.Type.DELETE) { | |||
b.add(peeledRef(walk, cmd)); | |||
} | |||
cmdIdx++; | |||
refIdx++; | |||
} | |||
} | |||
return b.toRefList(); | |||
} | |||
@@ -501,15 +508,6 @@ class PackedBatchRefUpdate extends BatchRefUpdate { | |||
} | |||
} | |||
private static Map<String, ReceiveCommand> byName( | |||
List<ReceiveCommand> commands) { | |||
Map<String, ReceiveCommand> ret = new LinkedHashMap<>(); | |||
for (ReceiveCommand cmd : commands) { | |||
ret.put(cmd.getRefName(), cmd); | |||
} | |||
return ret; | |||
} | |||
private static Ref peeledRef(RevWalk walk, ReceiveCommand cmd) | |||
throws IOException { | |||
ObjectId newId = cmd.getNewId().copy(); |