* stable-5.2: 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: I7e88c7c7d202f1e3fb8e143277650aa5fefff439 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,19 +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.3.4"/> | |||
<message_argument value="5.3.0"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="5.3.5"/> | |||
<message_argument value="5.3.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,17 +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.3.4"/> | |||
<message_argument value="5.3.0"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="5.3.5"/> | |||
<message_argument value="5.3.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,19 +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.3.4"/> | |||
<message_argument value="5.3.0"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="5.3.5"/> | |||
<message_argument value="5.3.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> | |||
@@ -68,6 +54,36 @@ | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lib/ObjectIdRef.java" type="org.eclipse.jgit.lib.ObjectIdRef"> | |||
<filter id="338722907"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.lib.ObjectIdRef"/> | |||
<message_argument value="ObjectIdRef(Ref.Storage, String, ObjectId)"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lib/Ref.java" type="org.eclipse.jgit.lib.Ref"> | |||
<filter id="404000815"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.lib.Ref"/> | |||
<message_argument value="getUpdateIndex()"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/lib/RefDatabase.java" type="org.eclipse.jgit.lib.RefDatabase"> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.lib.RefDatabase"/> | |||
<message_argument value="exactRef(String)"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="421654647"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.lib.RefDatabase"/> | |||
<message_argument value="getRef(String)"/> | |||
</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> | |||
@@ -124,6 +140,58 @@ | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/transport/BaseReceivePack.java" type="org.eclipse.jgit.transport.BaseReceivePack"> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> | |||
<message_argument value="getAdvertisedRefs()"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> | |||
<message_argument value="getPushCertificate()"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> | |||
<message_argument value="getRepository()"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> | |||
<message_argument value="getRevWalk()"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> | |||
<message_argument value="setAdvertisedRefs(Map<String,Ref>, Set<ObjectId>)"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="421650549"> | |||
<message_arguments> | |||
<message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> | |||
<message_argument value="setPushCertificate(PushCertificate)"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/transport/TransferConfig.java" type="org.eclipse.jgit.transport.TransferConfig"> | |||
<filter id="1159725059"> | |||
<message_arguments> | |||
<message_argument value="5.1.4"/> | |||
<message_argument value="TransferConfig(Config)"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="1159725059"> | |||
<message_arguments> | |||
<message_argument value="5.1.4"/> | |||
<message_argument value="TransferConfig(Repository)"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator"> | |||
<filter id="1142947843"> | |||
<message_arguments> | |||
@@ -147,6 +215,12 @@ | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS"> | |||
<filter id="1142947843"> | |||
<message_arguments> | |||
<message_argument value="4.5.6"/> | |||
<message_argument value="fileAttributes(File)"/> | |||
</message_arguments> | |||
</filter> | |||
<filter id="1142947843"> | |||
<message_arguments> | |||
<message_argument value="5.1.9"/> |
@@ -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(); |