diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java | 435 |
1 files changed, 359 insertions, 76 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java index 60043fff76..5333beff4b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java @@ -1,127 +1,274 @@ /* - * Copyright (C) 2008-2009, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2008, 2023 Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * 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. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.transport; +import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase; +import static org.eclipse.jgit.util.StringUtils.toLowerCase; + +import java.io.File; +import java.util.EnumSet; import java.util.HashMap; import java.util.Map; +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.internal.storage.file.LazyObjectIdSetFile; import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Config.SectionParser; import org.eclipse.jgit.lib.ObjectChecker; +import org.eclipse.jgit.lib.ObjectIdSet; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.util.SystemReader; /** - * The standard "transfer", "fetch", "receive", and "uploadpack" configuration - * parameters. + * The standard "transfer", "fetch", "protocol", "receive", and "uploadpack" + * configuration parameters. */ public class TransferConfig { + private static final String FSCK = "fsck"; //$NON-NLS-1$ + /** Key for {@link Config#get(SectionParser)}. */ - public static final Config.SectionParser<TransferConfig> KEY = new SectionParser<TransferConfig>() { - public TransferConfig parse(final Config cfg) { - return new TransferConfig(cfg); + public static final Config.SectionParser<TransferConfig> KEY = + TransferConfig::new; + + /** + * A git configuration value for how to handle a fsck failure of a particular kind. + * Used in e.g. fsck.missingEmail. + * @since 4.9 + */ + public enum FsckMode { + /** + * Treat it as an error (the default). + */ + ERROR, + /** + * Issue a warning (in fact, jgit treats this like IGNORE, but git itself does warn). + */ + WARN, + /** + * Ignore the error. + */ + IGNORE; + } + + /** + * A git configuration variable for which versions of the Git protocol to + * prefer. Used in protocol.version. + * + * @since 5.9 + */ + public enum ProtocolVersion { + /** + * Git wire protocol version 0 (the default). + */ + V0("0"), //$NON-NLS-1$ + /** + * Git wire protocol version 2. + */ + V2("2"); //$NON-NLS-1$ + + final String name; + + ProtocolVersion(String name) { + this.name = name; + } + + /** + * Returns version number + * + * @return string version + */ + public String version() { + return name; } - }; - private final boolean checkReceivedObjects; - private final boolean allowLeadingZeroFileMode; + @Nullable + static ProtocolVersion parse(@Nullable String name) { + if (name == null) { + return null; + } + for (ProtocolVersion v : ProtocolVersion.values()) { + if (v.name.equals(name)) { + return v; + } + } + if ("1".equals(name)) { //$NON-NLS-1$ + return V0; + } + return null; + } + } + + private final boolean fetchFsck; + private final boolean receiveFsck; + private final String fsckSkipList; + private final EnumSet<ObjectChecker.ErrorType> ignore; private final boolean allowInvalidPersonIdent; private final boolean safeForWindows; private final boolean safeForMacOS; + private final boolean allowRefInWant; private final boolean allowTipSha1InWant; - private final String[] hideRefs; + private final boolean allowReachableSha1InWant; + private final boolean allowAnySha1InWant; + private final boolean allowFilter; + private final boolean allowSidebandAll; + + private final boolean advertiseSidebandAll; + private final boolean advertiseWaitForDone; + private final boolean advertiseObjectInfo; - TransferConfig(final Repository db) { + private final boolean allowReceiveClientSID; + + final @Nullable ProtocolVersion protocolVersion; + final String[] hideRefs; + + /** + * Create a configuration honoring the repository's settings. + * + * @param db + * the repository to read settings from. The repository is not + * retained by the new configuration, instead its settings are + * copied during the constructor. + * @since 5.1.4 + */ + public TransferConfig(Repository db) { this(db.getConfig()); } - private TransferConfig(final Config rc) { - checkReceivedObjects = rc.getBoolean( - "fetch", "fsckobjects", //$NON-NLS-1$ //$NON-NLS-2$ - rc.getBoolean("transfer", "fsckobjects", false)); //$NON-NLS-1$ //$NON-NLS-2$ - allowLeadingZeroFileMode = checkReceivedObjects - && rc.getBoolean("fsck", "allowLeadingZeroFileMode", false); //$NON-NLS-1$ //$NON-NLS-2$ - allowInvalidPersonIdent = checkReceivedObjects - && rc.getBoolean("fsck", "allowInvalidPersonIdent", false); //$NON-NLS-1$ //$NON-NLS-2$ - safeForWindows = checkReceivedObjects - && rc.getBoolean("fsck", "safeForWindows", //$NON-NLS-1$ //$NON-NLS-2$ + /** + * Create a configuration honoring settings in a + * {@link org.eclipse.jgit.lib.Config}. + * + * @param rc + * the source to read settings from. The source is not retained + * by the new configuration, instead its settings are copied + * during the constructor. + * @since 5.1.4 + */ + @SuppressWarnings("nls") + public TransferConfig(Config rc) { + boolean fsck = rc.getBoolean("transfer", "fsckobjects", false); + fetchFsck = rc.getBoolean("fetch", "fsckobjects", fsck); + receiveFsck = rc.getBoolean("receive", "fsckobjects", fsck); + fsckSkipList = rc.getString(FSCK, null, "skipList"); + allowInvalidPersonIdent = rc.getBoolean(FSCK, "allowInvalidPersonIdent", + false); + safeForWindows = rc.getBoolean(FSCK, "safeForWindows", SystemReader.getInstance().isWindows()); - safeForMacOS = checkReceivedObjects - && rc.getBoolean("fsck", "safeForMacOS", //$NON-NLS-1$ //$NON-NLS-2$ + safeForMacOS = rc.getBoolean(FSCK, "safeForMacOS", SystemReader.getInstance().isMacOS()); - allowTipSha1InWant = rc.getBoolean( - "uploadpack", "allowtipsha1inwant", false); //$NON-NLS-1$ //$NON-NLS-2$ - hideRefs = rc.getStringList("uploadpack", null, "hiderefs"); //$NON-NLS-1$ //$NON-NLS-2$ - } + ignore = EnumSet.noneOf(ObjectChecker.ErrorType.class); + EnumSet<ObjectChecker.ErrorType> set = EnumSet + .noneOf(ObjectChecker.ErrorType.class); + for (String key : rc.getNames(FSCK)) { + if (equalsIgnoreCase(key, "skipList") + || equalsIgnoreCase(key, "allowLeadingZeroFileMode") + || equalsIgnoreCase(key, "allowInvalidPersonIdent") + || equalsIgnoreCase(key, "safeForWindows") + || equalsIgnoreCase(key, "safeForMacOS")) { + continue; + } - /** - * @return strictly verify received objects? - * @deprecated use {@link #newObjectChecker()} instead. - */ - @Deprecated - public boolean isFsckObjects() { - return checkReceivedObjects; + ObjectChecker.ErrorType id = FsckKeyNameHolder.parse(key); + if (id != null) { + switch (rc.getEnum(FSCK, null, key, FsckMode.ERROR)) { + case ERROR: + ignore.remove(id); + break; + case WARN: + case IGNORE: + ignore.add(id); + break; + } + set.add(id); + } + } + if (!set.contains(ObjectChecker.ErrorType.ZERO_PADDED_FILEMODE) + && rc.getBoolean(FSCK, "allowLeadingZeroFileMode", false)) { + ignore.add(ObjectChecker.ErrorType.ZERO_PADDED_FILEMODE); + } + + allowRefInWant = rc.getBoolean("uploadpack", "allowrefinwant", false); + allowTipSha1InWant = rc.getBoolean( + "uploadpack", "allowtipsha1inwant", false); + allowReachableSha1InWant = rc.getBoolean( + "uploadpack", "allowreachablesha1inwant", false); + allowAnySha1InWant = rc.getBoolean("uploadpack", "allowanysha1inwant", + false); + allowFilter = rc.getBoolean( + "uploadpack", "allowfilter", false); + protocolVersion = ProtocolVersion.parse(rc + .getString(ConfigConstants.CONFIG_PROTOCOL_SECTION, null, + ConfigConstants.CONFIG_KEY_VERSION)); + hideRefs = rc.getStringList("uploadpack", null, "hiderefs"); + allowSidebandAll = rc.getBoolean( + "uploadpack", "allowsidebandall", false); + advertiseSidebandAll = rc.getBoolean("uploadpack", + "advertisesidebandall", false); + advertiseWaitForDone = rc.getBoolean("uploadpack", + "advertisewaitfordone", false); + advertiseObjectInfo = rc.getBoolean("uploadpack", + "advertiseobjectinfo", false); + allowReceiveClientSID = rc.getBoolean("transfer", "advertisesid", + false); } /** + * Create checker to verify fetched objects + * * @return checker to verify fetched objects, or null if checking is not * enabled in the repository configuration. * @since 3.6 */ + @Nullable public ObjectChecker newObjectChecker() { - if (!checkReceivedObjects) + return newObjectChecker(fetchFsck); + } + + /** + * Create checker to verify objects pushed into this repository + * + * @return checker to verify objects pushed into this repository, or null if + * checking is not enabled in the repository configuration. + * @since 4.2 + */ + @Nullable + public ObjectChecker newReceiveObjectChecker() { + return newObjectChecker(receiveFsck); + } + + private ObjectChecker newObjectChecker(boolean check) { + if (!check) { return null; + } return new ObjectChecker() - .setAllowLeadingZeroFileMode(allowLeadingZeroFileMode) + .setIgnore(ignore) .setAllowInvalidPersonIdent(allowInvalidPersonIdent) .setSafeForWindows(safeForWindows) - .setSafeForMacOS(safeForMacOS); + .setSafeForMacOS(safeForMacOS) + .setSkipList(skipList()); + } + + private ObjectIdSet skipList() { + if (fsckSkipList != null && !fsckSkipList.isEmpty()) { + return new LazyObjectIdSetFile(new File(fsckSkipList)); + } + return null; } /** + * Whether to allow clients to request non-advertised tip SHA-1s + * * @return allow clients to request non-advertised tip SHA-1s? * @since 3.1 */ @@ -130,7 +277,102 @@ public class TransferConfig { } /** - * @return {@link RefFilter} respecting configured hidden refs. + * Whether to allow clients to request non-tip SHA-1s + * + * @return allow clients to request non-tip SHA-1s? + * @since 4.1 + */ + public boolean isAllowReachableSha1InWant() { + return allowReachableSha1InWant; + } + + /** + * Whether to allow clients to request any SHA-1s + * + * @return allow clients to request any SHA-1s? + * @since 6.5 + */ + public boolean isAllowAnySha1InWant() { + return allowAnySha1InWant; + } + + /** + * Whether clients are allowed to specify "filter" line + * + * @return true if clients are allowed to specify a "filter" line + * @since 5.0 + */ + public boolean isAllowFilter() { + return allowFilter; + } + + /** + * Whether clients are allowed to specify "want-ref" line + * + * @return true if clients are allowed to specify a "want-ref" line + * @since 5.1 + */ + public boolean isAllowRefInWant() { + return allowRefInWant; + } + + /** + * Whether the server accepts sideband-all requests + * + * @return true if the server accepts sideband-all requests (see + * {{@link #isAdvertiseSidebandAll()} for the advertisement) + * @since 5.5 + */ + public boolean isAllowSidebandAll() { + return allowSidebandAll; + } + + /** + * Whether to advertise sideband all to the clients + * + * @return true to advertise sideband all to the clients + * @since 5.6 + */ + public boolean isAdvertiseSidebandAll() { + return advertiseSidebandAll && allowSidebandAll; + } + + /** + * Whether to advertise wait-for-done all to the clients + * + * @return true to advertise wait-for-done all to the clients + * @since 5.13 + */ + public boolean isAdvertiseWaitForDone() { + return advertiseWaitForDone; + } + + /** + * Whether to advertise object-info to all clients + * + * @return true to advertise object-info to all clients + * @since 5.13 + */ + public boolean isAdvertiseObjectInfo() { + return advertiseObjectInfo; + } + + /** + * Whether to advertise and receive session-id capability + * + * @return true to advertise and receive session-id capability + * @since 6.4 + */ + public boolean isAllowReceiveClientSID() { + return allowReceiveClientSID; + } + + /** + * Get {@link org.eclipse.jgit.transport.RefFilter} respecting configured + * hidden refs. + * + * @return {@link org.eclipse.jgit.transport.RefFilter} respecting + * configured hidden refs. * @since 3.1 */ public RefFilter getRefFilter() { @@ -138,8 +380,9 @@ public class TransferConfig { return RefFilter.DEFAULT; return new RefFilter() { + @Override public Map<String, Ref> filter(Map<String, Ref> refs) { - Map<String, Ref> result = new HashMap<String, Ref>(); + Map<String, Ref> result = new HashMap<>(); for (Map.Entry<String, Ref> e : refs.entrySet()) { boolean add = true; for (String hide : hideRefs) { @@ -159,4 +402,44 @@ public class TransferConfig { } }; } + + /** + * Like {@code getRefFilter() == RefFilter.DEFAULT}, but faster. + * + * @return {@code true} if no ref filtering is needed because there + * are no configured hidden refs. + */ + boolean hasDefaultRefFilter() { + return hideRefs.length == 0; + } + + static class FsckKeyNameHolder { + private static final Map<String, ObjectChecker.ErrorType> errors; + + static { + errors = new HashMap<>(); + for (ObjectChecker.ErrorType m : ObjectChecker.ErrorType.values()) { + errors.put(keyNameFor(m.name()), m); + } + } + + @Nullable + static ObjectChecker.ErrorType parse(String key) { + return errors.get(toLowerCase(key)); + } + + private static String keyNameFor(String name) { + StringBuilder r = new StringBuilder(name.length()); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c != '_') { + r.append(c); + } + } + return toLowerCase(r.toString()); + } + + private FsckKeyNameHolder() { + } + } } |