Browse Source

Merge branch 'stable-4.5' into stable-4.6

* stable-4.5:
  Prepare 4.5.5-SNAPSHOT builds
  JGit v4.5.4.201711221230-r
  Fix LockFile semantics when running on NFS
  Honor trustFolderStats also when reading packed-refs
  Prepare 4.5.4-SNAPSHOT builds
  JGit v4.5.3.201708160445-r

Change-Id: Ie9c8e0d9172c8d53f075c284bf2a9677980d8dfb
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v4.9.1.201712030800-r
Matthias Sohn 6 years ago
parent
commit
3ac44f1b38

+ 0
- 17
org.eclipse.jgit.lfs.server/.settings/.api_filters View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.jgit.lfs.server" version="2">
<resource path="src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java" type="org.eclipse.jgit.lfs.server.LfsProtocolServlet">
<filter comment="breaking implementors only which is ok under OSGi semver rules" id="336695337">
<message_arguments>
<message_argument value="org.eclipse.jgit.lfs.server.LfsProtocolServlet"/>
<message_argument value="getLargeFileRepository(LfsProtocolServlet.LfsRequest, String)"/>
</message_arguments>
</filter>
<filter comment="breaking implementors only which is ok under OSGi semver rules" id="338792546">
<message_arguments>
<message_argument value="org.eclipse.jgit.lfs.server.LfsProtocolServlet"/>
<message_argument value="getLargeFileRepository()"/>
</message_arguments>
</filter>
</resource>
</component>

+ 0
- 17
org.eclipse.jgit.lfs/.settings/.api_filters View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.jgit.lfs" version="2">
<resource path="src/org/eclipse/jgit/lfs/lib/Constants.java" type="org.eclipse.jgit.lfs.lib.Constants">
<filter id="388100214">
<message_arguments>
<message_argument value="org.eclipse.jgit.lfs.lib.Constants"/>
<message_argument value="CONTENT_TYPE_GIT_LFS_JSON"/>
</message_arguments>
</filter>
<filter id="388100214">
<message_arguments>
<message_argument value="org.eclipse.jgit.lfs.lib.Constants"/>
<message_argument value="HDR_APPLICATION_OCTET_STREAM"/>
</message_arguments>
</filter>
</resource>
</component>

+ 61
- 3
org.eclipse.jgit/.settings/.api_filters View File

@@ -1,10 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.jgit" version="2">
<resource path="META-INF/MANIFEST.MF">
<filter comment="non-breaking addition of exception classes needed to cleanly fix error handling in PackFile" id="924844039">
<filter id="924844039">
<message_arguments>
<message_argument value="4.5.2"/>
<message_argument value="4.5.0"/>
<message_argument value="4.6.2"/>
<message_argument value="4.6.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/jgit/errors/NoPackSignatureException.java" type="org.eclipse.jgit.errors.NoPackSignatureException">
<filter id="1108344834">
<message_arguments>
<message_argument value="4.5"/>
<message_argument value="4.6"/>
<message_argument value="org.eclipse.jgit.errors.NoPackSignatureException"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/jgit/errors/UnsupportedPackIndexVersionException.java" type="org.eclipse.jgit.errors.UnsupportedPackIndexVersionException">
<filter id="1108344834">
<message_arguments>
<message_argument value="4.5"/>
<message_argument value="4.6"/>
<message_argument value="org.eclipse.jgit.errors.UnsupportedPackIndexVersionException"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/jgit/errors/UnsupportedPackVersionException.java" type="org.eclipse.jgit.errors.UnsupportedPackVersionException">
<filter id="1108344834">
<message_arguments>
<message_argument value="4.5"/>
<message_argument value="4.6"/>
<message_argument value="org.eclipse.jgit.errors.UnsupportedPackVersionException"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
<filter id="336658481">
<message_arguments>
<message_argument value="org.eclipse.jgit.lib.ConfigConstants"/>
<message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/>
</message_arguments>
</filter>
<filter id="1141899266">
<message_arguments>
<message_argument value="4.5"/>
<message_argument value="4.6"/>
<message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS">
<filter id="1141899266">
<message_arguments>
<message_argument value="4.5"/>
<message_argument value="4.6"/>
<message_argument value="createNewFile(File)"/>
</message_arguments>
</filter>
<filter id="1141899266">
<message_arguments>
<message_argument value="4.5"/>
<message_argument value="4.6"/>
<message_argument value="supportsAtomicCreateNewFile()"/>
</message_arguments>
</filter>
</resource>

+ 1
- 1
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java View File

@@ -168,7 +168,7 @@ public class LockFile {
*/
public boolean lock() throws IOException {
FileUtils.mkdirs(lck.getParentFile(), true);
if (lck.createNewFile()) {
if (FS.DETECTED.createNewFile(lck)) {
haveLck = true;
try {
os = new FileOutputStream(lck);

+ 9
- 2
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java View File

@@ -80,6 +80,7 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.ObjectWritingException;
import org.eclipse.jgit.events.RefsChangedEvent;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
@@ -765,14 +766,20 @@ public class RefDirectory extends RefDatabase {
}

private PackedRefList getPackedRefs() throws IOException {
boolean trustFolderStat = getRepository().getConfig().getBoolean(
ConfigConstants.CONFIG_CORE_SECTION,
ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true);

final PackedRefList curList = packedRefs.get();
if (!curList.snapshot.isModified(packedRefsFile))
if (trustFolderStat && !curList.snapshot.isModified(packedRefsFile)) {
return curList;
}

final PackedRefList newList = readPackedRefs();
if (packedRefs.compareAndSet(curList, newList)
&& !curList.id.equals(newList.id))
&& !curList.id.equals(newList.id)) {
modCnt.incrementAndGet();
}
return newList;
}


+ 7
- 0
org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java View File

@@ -326,6 +326,13 @@ public class ConfigConstants {
*/
public static final String CONFIG_KEY_TRUSTFOLDERSTAT = "trustfolderstat";

/**
* The "supportsAtomicFileCreation" key in the "core section"
*
* @since 4.5
*/
public static final String CONFIG_KEY_SUPPORTSATOMICFILECREATION = "supportsatomicfilecreation";

/**
* The "noprefix" key in the "diff section"
* @since 3.0

+ 31
- 0
org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java View File

@@ -236,6 +236,21 @@ public abstract class FS {
*/
public abstract boolean supportsExecute();

/**
* Does this file system support atomic file creation via
* java.io.File#createNewFile()? In certain environments (e.g. on NFS) it is
* not guaranteed that when two file system clients run createNewFile() in
* parallel only one will succeed. In such cases both clients may think they
* created a new file.
*
* @return true if this implementation support atomic creation of new
* Files by {@link File#createNewFile()}
* @since 4.5
*/
public boolean supportsAtomicCreateNewFile() {
return true;
}

/**
* Does this operating system and JRE supports symbolic links. The
* capability to handle symbolic links is detected at runtime.
@@ -776,6 +791,22 @@ public abstract class FS {
FileUtils.createSymLink(path, target);
}

/**
* Create a new file. See {@link File#createNewFile()}. Subclasses of this
* class may take care to provide a safe implementation for this even if
* {@link #supportsAtomicCreateNewFile()} is <code>false</code>
*
* @param path
* the file to be created
* @return <code>true</code> if the file was created, <code>false</code> if
* the file already existed
* @throws IOException
* @since 4.5
*/
public boolean createNewFile(File path) throws IOException {
return path.createNewFile();
}

/**
* See {@link FileUtils#relativize(String, String)}.
*

+ 86
- 0
org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java View File

@@ -50,6 +50,7 @@ import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,8 +59,11 @@ import java.util.Set;

import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.CommandFailedException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -74,6 +78,10 @@ public class FS_POSIX extends FS {
private static final int DEFAULT_UMASK = 0022;
private volatile int umask = -1;

private volatile boolean supportsUnixNLink = true;

private volatile Boolean supportsAtomicCreateNewFile;

/** Default constructor. */
protected FS_POSIX() {
}
@@ -91,6 +99,33 @@ public class FS_POSIX extends FS {
}
}

private void determineAtomicFileCreationSupport() {
// @TODO: enhance SystemReader to support this without copying code
Boolean ret = getAtomicFileCreationSupportOption(
SystemReader.getInstance().openUserConfig(null, this));
if (ret == null && StringUtils.isEmptyOrNull(SystemReader.getInstance()
.getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
ret = getAtomicFileCreationSupportOption(
SystemReader.getInstance().openSystemConfig(null, this));
}
supportsAtomicCreateNewFile = (ret == null) || ret;
}

private Boolean getAtomicFileCreationSupportOption(FileBasedConfig config) {
try {
config.load();
String value = config.getString(ConfigConstants.CONFIG_CORE_SECTION,
null,
ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION);
if (value == null) {
return null;
}
return Boolean.valueOf(StringUtils.toBoolean(value));
} catch (IOException | ConfigInvalidException e) {
return Boolean.TRUE;
}
}

@Override
public FS newInstance() {
return new FS_POSIX(this);
@@ -301,4 +336,55 @@ public class FS_POSIX extends FS {
return hookPath.toFile();
return null;
}

@Override
public boolean supportsAtomicCreateNewFile() {
if (supportsAtomicCreateNewFile == null) {
determineAtomicFileCreationSupport();
}
return supportsAtomicCreateNewFile.booleanValue();
}

@SuppressWarnings("boxing")
/**
* An implementation of the File#createNewFile() semantics which works also
* on NFS. If the config option
* {@code core.supportsAtomicCreateNewFile = true} (which is the default)
* then simply File#createNewFile() is called.
*
* But if {@code core.supportsAtomicCreateNewFile = false} then after
* successful creation of the lock file a hardlink to that lock file is
* created and the attribute nlink of the lock file is checked to be 2. If
* multiple clients manage to create the same lock file nlink would be
* greater than 2 showing the error.
*
* @see https://www.time-travellers.org/shane/papers/NFS_considered_harmful.html
* @since 4.5
*/
public boolean createNewFile(File lock) throws IOException {
if (!lock.createNewFile()) {
return false;
}
if (supportsAtomicCreateNewFile() || !supportsUnixNLink) {
return true;
}
Path lockPath = lock.toPath();
Path link = Files.createLink(Paths.get(lock.getAbsolutePath() + ".lnk"), //$NON-NLS-1$
lockPath);
try {
Integer nlink = (Integer) (Files.getAttribute(lockPath,
"unix:nlink")); //$NON-NLS-1$
if (nlink != 2) {
LOG.warn("nlink of link to lock file {0} was not 2 but {1}", //$NON-NLS-1$
lock.getPath(), nlink);
return false;
}
return true;
} catch (UnsupportedOperationException | IllegalArgumentException e) {
supportsUnixNLink = false;
return true;
} finally {
Files.delete(link);
}
}
}

Loading…
Cancel
Save