<commit_before>package me.nallar.modpatcher;

import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import me.nallar.javapatcher.patcher.Patcher;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.nio.file.FileSystem;
import java.nio.file.*;
import java.util.concurrent.*;

/**
 * ModPatcher API
 *
 * This class is the public facing API of ModPatcher
 *
 * It automatically downloads ModPatcher if the file is missing from the libs folder, or a coremod depends on
 * a newer version of modpatcher than the installed version
 *
 * This behaviour can be disabled by creating the file "libs/modpatcher/NEVER_UPDATE.txt"
 */
public class ModPatcher {
	private static final int API_VERSION = 0;
	private static final Logger log = LogManager.getLogger("ModPatcher");
	private static final String mcVersion = "@MC_VERSION@";
	private static final Path neverUpdatePath = Paths.get("./libs/ModPatcher/NEVER_UPDATE.txt").toAbsolutePath();
	private static final Path modPatcherPath = Paths.get("./libs/ModPatcher/ModPatcher-lib.jar").toAbsolutePath();
	private static final Future<Boolean> defaultUpdateRequired = CompletableFuture.completedFuture(Files.exists(modPatcherPath));
	private static String modPatcherRelease;
	private static Future<Boolean> updateRequired = defaultUpdateRequired;
	private static Version requiredVersion;
	private static Version lastVersion;

	/**
	 * Gets the name of the setup class to use in your IFMLLoadingPlugin
	 *
	 * @return Name of the ModPatcher setup class
	 */
	public static String getSetupClass() {
		return getSetupClass(null);
	}

	/**
	 * Gets the name of the setup class to use in your IFMLLoadingPlugin
	 *
	 * @param versionString Minimum version of ModPatcher required. Special value "latest" always uses latest version
	 * @return Name of the ModPatcher setup class
	 */
	public static String getSetupClass(String versionString) {
		return getSetupClass(versionString, null);
	}

	/**
	 * Gets the name of the setup class to use in your IFMLLoadingPlugin
	 *
	 * @param versionString Minimum version of ModPatcher required. Special value "latest" always uses latest version
	 * @param release       Release stream to use
	 * @return Name of the ModPatcher setup class
	 */
	public static String getSetupClass(String versionString, String release) {
		if (versionString != null || release != null) {
			if (updateRequired == null) {
				throw new Error("Modpatcher has already been loaded, it is too late to call getSetupClass");
			}
			if (release != null) {
				if (modPatcherRelease == null) {
					modPatcherRelease = release;
					startVersionCheck();
				} else {
					log.warn("Conflicting ModPatcher release requests. Set to " + modPatcherRelease + ", requested: " + release);
				}
			}
			if (versionString != null) {
				Version requested = Version.of(versionString);
				if (requested.compareTo(requiredVersion) > 0) {
					requiredVersion = requested;
					startVersionCheck();
				}
			}
		}

		return "me.nallar.modpatcher.ModPatcherSetup";
	}

	/**
	 * Load JavaPatcher patches
	 *
	 * @param inputStream stream to load patches from
	 */
	public static void loadPatches(InputStream inputStream) {
		getPatcher().loadPatches(inputStream);
	}

	/**
	 * Load JavaPatcher patches
	 *
	 * @param patches String to load patches from
	 */
	public static void loadPatches(String patches) {
		getPatcher().loadPatches(patches);
	}

	/**
	 * Gets the JavaPatcher Patcher instance
	 *
	 * @deprecated Use specific methods such as loadPatches(InputStream)
	 * @return the Patcher
	 */
	@Deprecated
	public static Patcher getPatcher() {
		checkClassLoading();
		return ModPatcherTransformer.getPatcher();
	}

	/**
	 * Loads mixins from the given package.
	 * The package must have a package-info.java with @Mixin annotation
	 *
	 * @param mixinPackage Package to load mixins from
	 */
	public static void loadMixins(String mixinPackage) {
		checkClassLoading();
		ModPatcherTransformer.getMixinApplicator().addSource(mixinPackage);
	}

	/**
	 * Loads all mixins from the given path, regardless of package
	 *
	 * @param path Path to load mixins from
	 */
	public static void loadMixins(Path path) {
		checkClassLoading();
		ModPatcherTransformer.getMixinApplicator().addSource(path);
	}

	/**
	 * Loads all mixins from the given path, if they match the given package
	 *
	 * @param path Path to load mixins from
	 */
	public static void loadMixins(Path path, String packageName) {
		checkClassLoading();
		ModPatcherTransformer.getMixinApplicator().addSource(path, packageName);
	}

	/**
	 * Gets the default patches directory. Any patches in this directory are loaded by ModPatcher on startup.
	 *
	 * @return default patches directory
	 */
	public static String getDefaultPatchesDirectory() {
		checkClassLoading();
		return ModPatcherTransformer.getDefaultPatchesDirectory();
	}


	private static void loadModPatcher() {
		download();

		updateRequired = null;

		addToCurrentClassLoader();

		checkClassLoading();
	}

	private static String getModPatcherRelease() {
		return mcVersion + '-' + System.getProperty("modpatcher.release", modPatcherRelease == null ? "stable" : modPatcherRelease);
	}

	@SuppressWarnings("unchecked")
	private static void addToCurrentClassLoader() {
		ClassLoader cl = ModPatcher.class.getClassLoader();

		if (cl instanceof LaunchClassLoader) {
			LaunchClassLoader lcl = (LaunchClassLoader) cl;
			cl = ReflectionHelper.<ClassLoader, LaunchClassLoader>getPrivateValue(LaunchClassLoader.class, lcl, "parent");
			lcl.addTransformerExclusion("me.nallar.modpatcher");
		}

		try {
			Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
			method.setAccessible(true);
			method.invoke(cl, modPatcherPath.toUri().toURL());
		} catch (Exception e) {
			throw new Error(e);
		}
	}
<commit_msg>Prevent infinite recursion if downloading fails<commit_after>package me.nallar.modpatcher;

import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import me.nallar.javapatcher.patcher.Patcher;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.nio.file.FileSystem;
import java.nio.file.*;
import java.util.concurrent.*;

/**
 * ModPatcher API
 *
 * This class is the public facing API of ModPatcher
 *
 * It automatically downloads ModPatcher if the file is missing from the libs folder, or a coremod depends on
 * a newer version of modpatcher than the installed version
 *
 * This behaviour can be disabled by creating the file "libs/modpatcher/NEVER_UPDATE.txt"
 */
public class ModPatcher {
	private static final int API_VERSION = 0;
	private static final Logger log = LogManager.getLogger("ModPatcher");
	private static final String mcVersion = "@MC_VERSION@";
	private static final Path neverUpdatePath = Paths.get("./libs/ModPatcher/NEVER_UPDATE.txt").toAbsolutePath();
	private static final Path modPatcherPath = Paths.get("./libs/ModPatcher/ModPatcher-lib.jar").toAbsolutePath();
	private static final Future<Boolean> defaultUpdateRequired = CompletableFuture.completedFuture(Files.exists(modPatcherPath));
	private static String modPatcherRelease;
	private static Future<Boolean> updateRequired = defaultUpdateRequired;
	private static Version requiredVersion;
	private static Version lastVersion;

	/**
	 * Gets the name of the setup class to use in your IFMLLoadingPlugin
	 *
	 * @return Name of the ModPatcher setup class
	 */
	public static String getSetupClass() {
		return getSetupClass(null);
	}

	/**
	 * Gets the name of the setup class to use in your IFMLLoadingPlugin
	 *
	 * @param versionString Minimum version of ModPatcher required. Special value "latest" always uses latest version
	 * @return Name of the ModPatcher setup class
	 */
	public static String getSetupClass(String versionString) {
		return getSetupClass(versionString, null);
	}

	/**
	 * Gets the name of the setup class to use in your IFMLLoadingPlugin
	 *
	 * @param versionString Minimum version of ModPatcher required. Special value "latest" always uses latest version
	 * @param release       Release stream to use
	 * @return Name of the ModPatcher setup class
	 */
	public static String getSetupClass(String versionString, String release) {
		if (versionString != null || release != null) {
			if (updateRequired == null) {
				throw new Error("Modpatcher has already been loaded, it is too late to call getSetupClass");
			}
			if (release != null) {
				if (modPatcherRelease == null) {
					modPatcherRelease = release;
					startVersionCheck();
				} else {
					log.warn("Conflicting ModPatcher release requests. Set to " + modPatcherRelease + ", requested: " + release);
				}
			}
			if (versionString != null) {
				Version requested = Version.of(versionString);
				if (requested.compareTo(requiredVersion) > 0) {
					requiredVersion = requested;
					startVersionCheck();
				}
			}
		}

		return "me.nallar.modpatcher.ModPatcherSetup";
	}

	/**
	 * Load JavaPatcher patches
	 *
	 * @param inputStream stream to load patches from
	 */
	public static void loadPatches(InputStream inputStream) {
		getPatcher().loadPatches(inputStream);
	}

	/**
	 * Load JavaPatcher patches
	 *
	 * @param patches String to load patches from
	 */
	public static void loadPatches(String patches) {
		getPatcher().loadPatches(patches);
	}

	/**
	 * Gets the JavaPatcher Patcher instance
	 *
	 * @deprecated Use specific methods such as loadPatches(InputStream)
	 * @return the Patcher
	 */
	@Deprecated
	public static Patcher getPatcher() {
		checkClassLoading();
		return ModPatcherTransformer.getPatcher();
	}

	/**
	 * Loads mixins from the given package.
	 * The package must have a package-info.java with @Mixin annotation
	 *
	 * @param mixinPackage Package to load mixins from
	 */
	public static void loadMixins(String mixinPackage) {
		checkClassLoading();
		ModPatcherTransformer.getMixinApplicator().addSource(mixinPackage);
	}

	/**
	 * Loads all mixins from the given path, regardless of package
	 *
	 * @param path Path to load mixins from
	 */
	public static void loadMixins(Path path) {
		checkClassLoading();
		ModPatcherTransformer.getMixinApplicator().addSource(path);
	}

	/**
	 * Loads all mixins from the given path, if they match the given package
	 *
	 * @param path Path to load mixins from
	 */
	public static void loadMixins(Path path, String packageName) {
		checkClassLoading();
		ModPatcherTransformer.getMixinApplicator().addSource(path, packageName);
	}

	/**
	 * Gets the default patches directory. Any patches in this directory are loaded by ModPatcher on startup.
	 *
	 * @return default patches directory
	 */
	public static String getDefaultPatchesDirectory() {
		checkClassLoading();
		return ModPatcherTransformer.getDefaultPatchesDirectory();
	}

	private static void loadModPatcher() {
		download();

		updateRequired = null;

		addToCurrentClassLoader();

		checkClassLoading(false);
	}

	private static String getModPatcherRelease() {
		return mcVersion + '-' + System.getProperty("modpatcher.release", modPatcherRelease == null ? "stable" : modPatcherRelease);
	}

	@SuppressWarnings("unchecked")
	private static void addToCurrentClassLoader() {
		ClassLoader cl = ModPatcher.class.getClassLoader();

		if (cl instanceof LaunchClassLoader) {
			LaunchClassLoader lcl = (LaunchClassLoader) cl;
			cl = ReflectionHelper.<ClassLoader, LaunchClassLoader>getPrivateValue(LaunchClassLoader.class, lcl, "parent");
			lcl.addTransformerExclusion("me.nallar.modpatcher");
		}

		try {
			Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
			method.setAccessible(true);
			method.invoke(cl, modPatcherPath.toUri().toURL());
		} catch (Exception e) {
			throw new Error(e);
		}
	}

{'fraction_non_alphanumeric': 0.09458567183889072, 'fraction_numerical': 0.0006602839220864972, 'mean_word_length': 4.397327394209354, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1210610', 'n_tokens_mistral': 3760, 'n_tokens_neox': 3410, 'n_words': 1045}