TransferConfig.java
- /*
- * Copyright (C) 2008, 2020 Google Inc. and others
- *
- * 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.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", "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 =
- 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;
- }
- @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 boolean allowReachableSha1InWant;
- private final boolean allowFilter;
- private final boolean allowSidebandAll;
- private final boolean advertiseSidebandAll;
- 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());
- }
- /**
- * 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 = rc.getBoolean(FSCK, "safeForMacOS",
- SystemReader.getInstance().isMacOS());
- 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;
- }
- 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);
- 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);
- }
- /**
- * 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() {
- 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()
- .setIgnore(ignore)
- .setAllowInvalidPersonIdent(allowInvalidPersonIdent)
- .setSafeForWindows(safeForWindows)
- .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
- */
- public boolean isAllowTipSha1InWant() {
- return allowTipSha1InWant;
- }
- /**
- * 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;
- }
- /**
- * @return true if clients are allowed to specify a "filter" line
- * @since 5.0
- */
- public boolean isAllowFilter() {
- return allowFilter;
- }
- /**
- * @return true if clients are allowed to specify a "want-ref" line
- * @since 5.1
- */
- public boolean isAllowRefInWant() {
- return allowRefInWant;
- }
- /**
- * @return true if the server accepts sideband-all requests (see
- * {{@link #isAdvertiseSidebandAll()} for the advertisement)
- * @since 5.5
- */
- public boolean isAllowSidebandAll() {
- return allowSidebandAll;
- }
- /**
- * @return true to advertise sideband all to the clients
- * @since 5.6
- */
- public boolean isAdvertiseSidebandAll() {
- return advertiseSidebandAll && allowSidebandAll;
- }
- /**
- * 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() {
- if (hideRefs.length == 0)
- return RefFilter.DEFAULT;
- return new RefFilter() {
- @Override
- public Map<String, Ref> filter(Map<String, Ref> refs) {
- Map<String, Ref> result = new HashMap<>();
- for (Map.Entry<String, Ref> e : refs.entrySet()) {
- boolean add = true;
- for (String hide : hideRefs) {
- if (e.getKey().equals(hide) || prefixMatch(hide, e.getKey())) {
- add = false;
- break;
- }
- }
- if (add)
- result.put(e.getKey(), e.getValue());
- }
- return result;
- }
- private boolean prefixMatch(String p, String s) {
- return p.charAt(p.length() - 1) == '/' && s.startsWith(p);
- }
- };
- }
- /**
- * 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() {
- }
- }
- }