diff options
Diffstat (limited to 'org.eclipse.jgit.lfs')
7 files changed, 234 insertions, 26 deletions
diff --git a/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties b/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties index 0e00f146ae..642b83db44 100644 --- a/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties +++ b/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties @@ -1,19 +1,19 @@ corruptLongObject=The content hash ''{0}'' of the long object ''{1}'' doesn''t match its id, the corrupt object will be deleted. -incorrectLONG_OBJECT_ID_LENGTH=Incorrect LONG_OBJECT_ID_LENGTH. -inconsistentMediafileLength=Mediafile {0} has unexpected length; expected {1} but found {2}. +dotLfsConfigReadFailed=Reading .lfsconfig failed inconsistentContentLength=Unexpected content length reported by LFS server ({0}), expected {1} but reported was {2} +inconsistentMediafileLength=Mediafile {0} has unexpected length; expected {1} but found {2}. +incorrectLONG_OBJECT_ID_LENGTH=Incorrect LONG_OBJECT_ID_LENGTH. invalidLongId=Invalid id: {0} invalidLongIdLength=Invalid id length {0}; should be {1} +lfsFailedToGetRepository=failed to get repository {0} +lfsNoDownloadUrl="Need to download object from LFS server but couldn't determine LFS server URL" +lfsUnauthorized=Not authorized to perform operation {0} on repository {1} lfsUnavailable=LFS is not available for repository {0} +missingLocalObject="Local Object {0} is missing" protocolError=LFS Protocol Error {0}: {1} -requiredHashFunctionNotAvailable=Required hash function {0} not available. repositoryNotFound=Repository {0} not found repositoryReadOnly=Repository {0} is read-only -lfsUnavailable=LFS is not available for repository {0} -lfsUnathorized=Not authorized to perform operation {0} on repository {1} -lfsFailedToGetRepository=failed to get repository {0} -lfsNoDownloadUrl="Need to download object from LFS server but couldn't determine LFS server URL" +requiredHashFunctionNotAvailable=Required hash function {0} not available. serverFailure=When trying to open a connection to {0} the server responded with an error code. rc={1} -wrongAmoutOfDataReceived=While downloading data from the content server {0} {1} bytes have been received while {2} have been expected userConfigInvalid="User config file {0} invalid {1}" -missingLocalObject="Local Object {0} is missing"
\ No newline at end of file +wrongAmountOfDataReceived=While downloading data from the content server {0} {1} bytes have been received while {2} have been expected
\ No newline at end of file diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java index 3411887567..c26a1bfbb3 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java @@ -205,7 +205,7 @@ public class SmudgeFilter extends FilterCommand { long bytesCopied = Files.copy(contentIn, path); if (bytesCopied != o.size) { throw new IOException(MessageFormat.format( - LfsText.get().wrongAmoutOfDataReceived, + LfsText.get().wrongAmountOfDataReceived, contentServerConn.getURL(), Long.valueOf(bytesCopied), Long.valueOf(o.size))); diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsUnauthorized.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsUnauthorized.java index 36889db8a6..0dc6aeab29 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsUnauthorized.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsUnauthorized.java @@ -31,7 +31,7 @@ public class LfsUnauthorized extends LfsException { * the repository name. */ public LfsUnauthorized(String operation, String name) { - super(MessageFormat.format(LfsText.get().lfsUnathorized, operation, + super(MessageFormat.format(LfsText.get().lfsUnauthorized, operation, name)); } } diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConfig.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConfig.java new file mode 100644 index 0000000000..71d395ca84 --- /dev/null +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConfig.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2022, Matthias Fromme <mfromme@dspace.de> + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.lfs.internal; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.lfs.errors.LfsConfigInvalidException; +import org.eclipse.jgit.lfs.lib.Constants; +import org.eclipse.jgit.lib.BlobBasedConfig; +import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.storage.file.FileBasedConfig; +import org.eclipse.jgit.treewalk.TreeWalk; + +import static org.eclipse.jgit.lib.Constants.HEAD; + +/** + * Encapsulate access to the .lfsconfig. + * + * According to the document + * https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-config.5.ronn + * the order to find the .lfsconfig file is: + * + * <pre> + * 1. in the root of the working tree + * 2. in the index + * 3. in the HEAD, for bare repositories this is the only place + * that is searched + * </pre> + * + * Values from the .lfsconfig are used only if not specified in another git + * config file to allow local override without modifiction of a committed file. + */ +public class LfsConfig { + private Repository db; + private Config delegate; + + /** + * Create a new instance of the LfsConfig. + * + * @param db + * the associated repo + * @throws IOException + */ + public LfsConfig(Repository db) throws IOException { + this.db = db; + delegate = this.load(); + } + + /** + * Read the .lfsconfig file from the repository + * + * @return The loaded lfs config or null if it does not exist + * + * @throws IOException + */ + private Config load() throws IOException { + Config result = null; + + if (!db.isBare()) { + result = loadFromWorkingTree(); + if (result == null) { + result = loadFromIndex(); + } + } + + if (result == null) { + result = loadFromHead(); + } + + if (result == null) { + result = emptyConfig(); + } + + return result; + } + + /** + * Try to read the lfs config from a file called .lfsconfig at the top level + * of the working tree. + * + * @return the config, or <code>null</code> + * @throws IOException + */ + @Nullable + private Config loadFromWorkingTree() + throws IOException { + File lfsConfig = db.getFS().resolve(db.getWorkTree(), + Constants.DOT_LFS_CONFIG); + if (lfsConfig.exists() && lfsConfig.isFile()) { + FileBasedConfig config = new FileBasedConfig(lfsConfig, db.getFS()); + try { + config.load(); + return config; + } catch (ConfigInvalidException e) { + throw new LfsConfigInvalidException( + LfsText.get().dotLfsConfigReadFailed, e); + } + } + return null; + } + + /** + * Try to read the lfs config from an entry called .lfsconfig contained in + * the index. + * + * @return the config, or <code>null</code> if the entry does not exist + * @throws IOException + */ + @Nullable + private Config loadFromIndex() + throws IOException { + try { + DirCacheEntry entry = db.readDirCache() + .getEntry(Constants.DOT_LFS_CONFIG); + if (entry != null) { + return new BlobBasedConfig(null, db, entry.getObjectId()); + } + } catch (ConfigInvalidException e) { + throw new LfsConfigInvalidException( + LfsText.get().dotLfsConfigReadFailed, e); + } + return null; + } + + /** + * Try to read the lfs config from an entry called .lfsconfig contained in + * the head revision. + * + * @return the config, or <code>null</code> if the file does not exist + * @throws IOException + */ + @Nullable + private Config loadFromHead() throws IOException { + try (RevWalk revWalk = new RevWalk(db)) { + ObjectId headCommitId = db.resolve(HEAD); + if (headCommitId == null) { + return null; + } + RevCommit commit = revWalk.parseCommit(headCommitId); + RevTree tree = commit.getTree(); + TreeWalk treewalk = TreeWalk.forPath(db, Constants.DOT_LFS_CONFIG, + tree); + if (treewalk != null) { + return new BlobBasedConfig(null, db, treewalk.getObjectId(0)); + } + } catch (ConfigInvalidException e) { + throw new LfsConfigInvalidException( + LfsText.get().dotLfsConfigReadFailed, e); + } + return null; + } + + /** + * Create an empty config as fallback to avoid null pointer checks. + * + * @return an empty config + */ + private Config emptyConfig() { + return new Config(); + } + + /** + * Get string value or null if not found. + * + * First tries to find the value in the git config files. If not found tries + * to find data in .lfsconfig. + * + * @param section + * the section + * @param subsection + * the subsection for the value + * @param name + * the key name + * @return a String value from the config, <code>null</code> if not found + */ + public String getString(final String section, final String subsection, + final String name) { + String result = db.getConfig().getString(section, subsection, name); + if (result == null) { + result = delegate.getString(section, subsection, name); + } + return result; + } +} diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java index 5a17d411c7..12b688d157 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java @@ -45,7 +45,6 @@ import org.eclipse.jgit.util.StringUtils; * Provides means to get a valid LFS connection for a given repository. */ public class LfsConnectionFactory { - private static final int SSH_AUTH_TIMEOUT_SECONDS = 30; private static final String SCHEME_HTTPS = "https"; //$NON-NLS-1$ private static final String SCHEME_SSH = "ssh"; //$NON-NLS-1$ @@ -104,19 +103,19 @@ public class LfsConnectionFactory { * additional headers that can be used to connect to LFS server * @return the URL for the LFS server. e.g. * "https://github.com/github/git-lfs.git/info/lfs" - * @throws LfsConfigInvalidException - * if the LFS config is invalid + * @throws IOException + * if the LFS config is invalid or cannot be accessed * @see <a href= * "https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md"> * Server Discovery documentation</a> */ - static String getLfsUrl(Repository db, String purpose, + private static String getLfsUrl(Repository db, String purpose, Map<String, String> additionalHeaders) - throws LfsConfigInvalidException { - StoredConfig config = db.getConfig(); + throws IOException { + LfsConfig config = new LfsConfig(db); String lfsUrl = config.getString(ConfigConstants.CONFIG_SECTION_LFS, - null, - ConfigConstants.CONFIG_KEY_URL); + null, ConfigConstants.CONFIG_KEY_URL); + Exception ex = null; if (lfsUrl == null) { String remoteUrl = null; @@ -124,6 +123,7 @@ public class LfsConnectionFactory { lfsUrl = config.getString(ConfigConstants.CONFIG_SECTION_LFS, remote, ConfigConstants.CONFIG_KEY_URL); + // This could be done better (more precise logic), but according // to https://github.com/git-lfs/git-lfs/issues/1759 git-lfs // generally only supports 'origin' in an integrated workflow. diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java index 1ca37a9f66..06234c1d90 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java @@ -28,21 +28,22 @@ public class LfsText extends TranslationBundle { // @formatter:off /***/ public String corruptLongObject; - /***/ public String inconsistentMediafileLength; + /***/ public String dotLfsConfigReadFailed; /***/ public String inconsistentContentLength; + /***/ public String inconsistentMediafileLength; /***/ public String incorrectLONG_OBJECT_ID_LENGTH; /***/ public String invalidLongId; /***/ public String invalidLongIdLength; + /***/ public String lfsFailedToGetRepository; + /***/ public String lfsNoDownloadUrl; + /***/ public String lfsUnauthorized; /***/ public String lfsUnavailable; + /***/ public String missingLocalObject; /***/ public String protocolError; - /***/ public String requiredHashFunctionNotAvailable; /***/ public String repositoryNotFound; /***/ public String repositoryReadOnly; - /***/ public String lfsUnathorized; - /***/ public String lfsFailedToGetRepository; - /***/ public String lfsNoDownloadUrl; + /***/ public String requiredHashFunctionNotAvailable; /***/ public String serverFailure; - /***/ public String wrongAmoutOfDataReceived; /***/ public String userConfigInvalid; - /***/ public String missingLocalObject; + /***/ public String wrongAmountOfDataReceived; } diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java index 3212a63504..9b41ec31f1 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java @@ -82,6 +82,13 @@ public final class Constants { public static final String ATTR_FILTER_DRIVER_PREFIX = "lfs/"; /** + * Config file name for lfs specific configuration + * + * @since 6.1 + */ + public static final String DOT_LFS_CONFIG = ".lfsconfig"; + + /** * Create a new digest function for objects. * * @return a new digest object. |