summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.lfs/src/org/eclipse
diff options
context:
space:
mode:
authorMatthias Fromme <MFromme@dspace.de>2022-01-03 13:06:34 +0100
committerMatthias Sohn <matthias.sohn@sap.com>2022-03-03 10:47:45 +0100
commita229072fcd701f3d1f8835b36db95ec65ec2a6a2 (patch)
tree9b6447cddb04c952f06802b36979d6c85de8ffff /org.eclipse.jgit.lfs/src/org/eclipse
parente2a484f33dffbb0d6e983c694bccc48dbbf58fa9 (diff)
downloadjgit-a229072fcd701f3d1f8835b36db95ec65ec2a6a2.tar.gz
jgit-a229072fcd701f3d1f8835b36db95ec65ec2a6a2.zip
Support for "lfs.url" from ".lfsconfig"
- New class LfsConfig to enrich repository configuration by settings from ".lfsconfig" file respecting configuration file precedence. - Adapted LfsConnectionFactory to use LfsConfig instead of directly using configuration from repository to calculate url of the lfs repository Bug: 578020 Change-Id: I156f4ec137c2e428136a2ca9b8a4011ecee2d915
Diffstat (limited to 'org.eclipse.jgit.lfs/src/org/eclipse')
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConfig.java200
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java16
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java1
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java7
4 files changed, 216 insertions, 8 deletions
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..22813ff64f 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
@@ -45,4 +45,5 @@ public class LfsText extends TranslationBundle {
/***/ public String wrongAmoutOfDataReceived;
/***/ public String userConfigInvalid;
/***/ public String missingLocalObject;
+ /***/ public String dotLfsConfigReadFailed;
}
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.