<commit_before>package aQute.lib.deployer;

import java.io.*;
import java.security.*;
import java.util.*;
import java.util.jar.*;
import java.util.regex.*;

import aQute.bnd.header.*;
import aQute.bnd.osgi.*;
import aQute.bnd.osgi.Verifier;
import aQute.bnd.service.*;
import aQute.bnd.version.*;
import aQute.lib.io.*;
import aQute.libg.command.*;
import aQute.libg.cryptography.*;
import aQute.service.reporter.*;

public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, RegistryPlugin, Actionable {
	public final static String	LOCATION		= "location";
	public final static String	READONLY		= "readonly";
	public final static String	NAME			= "name";
	public static final String	CMD_PATH		= "cmd.path";
	public static final String	CMD_INIT		= "cmd.init";
	public static final String	CMD_AFTER_PUT	= "cmd.after.put";
	public static final String	CMD_REFRESH		= "cmd.refresh";
	public static final String	CMD_BEFORE_PUT	= "cmd.before.put";
	public static final String	CMD_ABORT_PUT	= "cmd.abort.put";
	public static final String	CMD_SHELL		= "cmd.shell";
	static final PutOptions		DEFAULTOPTIONS	= new PutOptions();

	String						before;
	String						refresh;
	String						after;
	String						path;
	String						init;
	String						abort;
	String						shell;

	File[]						EMPTY_FILES		= new File[0];
	protected File				root;
	Registry					registry;
	boolean						canWrite		= true;
	Pattern						REPO_FILE		= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+|latest)\\.(jar|lib)");
	Reporter					reporter;
	boolean						dirty;
	String						name;
	boolean						inited;

	public FileRepo() {}

	public FileRepo(String name, File location, boolean canWrite) {
		this.name = name;
		this.root = location;
		this.canWrite = canWrite;
	}

	protected void init() throws Exception {
		if (inited)
			return;

		inited = true;
		if (!getRoot().isDirectory()) {
			getRoot().mkdirs();
		}
		exec(init, null);
	}

	public void setProperties(Map<String,String> map) {
		String location = map.get(LOCATION);
		if (location == null)
			throw new IllegalArgumentException("Location must be set on a FileRepo plugin");

		root = IO.getFile(IO.home, location);

		String readonly = map.get(READONLY);
		if (readonly != null && Boolean.valueOf(readonly).booleanValue())
			canWrite = false;

		name = map.get(NAME);
		before = map.get(CMD_BEFORE_PUT);
		refresh = map.get(CMD_REFRESH);
		after = map.get(CMD_AFTER_PUT);
		init = map.get(CMD_INIT);
		path = map.get(CMD_PATH);
		abort = map.get(CMD_ABORT_PUT);
		shell = map.get(CMD_SHELL);
	}

	/**
	 * Get a list of URLs to bundles that are constrained by the bsn and
	 * versionRange.
	 */
	private File[] get(String bsn, String versionRange) throws Exception {
		init();

		// If the version is set to project, we assume it is not
		// for us. A project repo will then get it.
		if (versionRange != null && versionRange.equals("project"))
			return null;

		//
		// Check if the entry exists
		//
		File f = new File(root, bsn);
		if (!f.isDirectory())
			return null;

		//
		// The version range we are looking for can
		// be null (for all) or a version range.
		//
		VersionRange range;
		if (versionRange == null || versionRange.equals("latest")) {
			range = new VersionRange("0");
		} else
			range = new VersionRange(versionRange);

		//
		// Iterator over all the versions for this BSN.
		// Create a sorted map over the version as key
		// and the file as URL as value. Only versions
		// that match the desired range are included in
		// this list.
		//
		File instances[] = f.listFiles();
		SortedMap<Version,File> versions = new TreeMap<Version,File>();
		for (int i = 0; i < instances.length; i++) {
			Matcher m = REPO_FILE.matcher(instances[i].getName());
			if (m.matches() && m.group(1).equals(bsn)) {
				String versionString = m.group(2);
				Version version;
				if (versionString.equals("latest"))
					version = new Version(Integer.MAX_VALUE);
				else
					version = new Version(versionString);

				if (range.includes(version) || versionString.equals(versionRange))
					versions.put(version, instances[i]);
			}
		}

		File[] files = versions.values().toArray(EMPTY_FILES);
		if ("latest".equals(versionRange) && files.length > 0) {
			return new File[] {
				files[files.length - 1]
			};
		}
		return files;
	}

	public boolean canWrite() {
		return canWrite;
	}

	protected PutResult putArtifact(File tmpFile, PutOptions options) throws Exception {
		assert (tmpFile != null);
		assert (options != null);

		Jar jar = null;
		try {
			dirty = true;

			jar = new Jar(tmpFile);

			Manifest manifest = jar.getManifest();
			if (manifest == null)
				throw new IllegalArgumentException("No manifest in JAR: " + jar);

			String bsn = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_SYMBOLICNAME);
			if (bsn == null)
				throw new IllegalArgumentException("No Bundle SymbolicName set");

			Parameters b = Processor.parseHeader(bsn, null);
			if (b.size() != 1)
				throw new IllegalArgumentException("Multiple bsn's specified " + b);

			for (String key : b.keySet()) {
				bsn = key;
				if (!Verifier.SYMBOLICNAME.matcher(bsn).matches())
					throw new IllegalArgumentException("Bundle SymbolicName has wrong format: " + bsn);
			}

			String versionString = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_VERSION);
			Version version;
			if (versionString == null)
				version = new Version();
			else
				version = new Version(versionString);

			if (reporter != null)
				reporter.trace("bsn=%s version=%s", bsn, version);

			File dir = new File(root, bsn);
			if (!dir.exists() && !dir.mkdirs()) {
				throw new IOException("Could not create directory " + dir);
			}
			String fName = bsn + "-" + version.getWithoutQualifier() + ".jar";
			File file = new File(dir, fName);

			boolean renamed = false;
			PutResult result = new PutResult();

			if (reporter != null)
				reporter.trace("updating %s ", file.getAbsolutePath());
			
			if (!file.exists() || file.lastModified() < jar.lastModified()) {
				if (file.exists()) {
					IO.delete(file);
				}
				IO.rename(tmpFile, file);
				
				renamed = true;
				result.artifact = file.toURI();

				if (reporter != null)
					reporter.progress(-1, "updated " + file.getAbsolutePath());

				fireBundleAdded(jar, file);
				
				// Eecute the after command
				exec(after, file);
			} else {
				if (reporter != null) {
					reporter.progress(-1, "Did not update " + jar + " because repo has a newer version");
					reporter.trace("NOT Updating " + fName + " (repo is newer)");
				}
			}

			File latest = new File(dir, bsn + "-latest.jar");
			boolean latestExists = latest.exists() && latest.isFile();
			boolean latestIsOlder = latestExists && (latest.lastModified() < jar.lastModified());
			if ((options.createLatest && !latestExists) || latestIsOlder) {
				if (latestExists) {
					IO.delete(latest);
				}
				if (!renamed) {
					IO.rename(tmpFile, latest);
				} else {
					IO.copy(file, latest);
				}
				result.latest = latest.toURI();
			}

			return result;
		}
		finally {
			if (jar != null) {
				jar.close();
			}
		}
	}<commit_msg>File check removed The old repo checked if the JAR was younger to prevent unnecessary writes. With the new interface this is not possible. Removed the check<commit_after>package aQute.lib.deployer;

import java.io.*;
import java.security.*;
import java.util.*;
import java.util.jar.*;
import java.util.regex.*;

import aQute.bnd.header.*;
import aQute.bnd.osgi.*;
import aQute.bnd.osgi.Verifier;
import aQute.bnd.service.*;
import aQute.bnd.version.*;
import aQute.lib.io.*;
import aQute.libg.command.*;
import aQute.libg.cryptography.*;
import aQute.service.reporter.*;

public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, RegistryPlugin, Actionable {
	public final static String	LOCATION		= "location";
	public final static String	READONLY		= "readonly";
	public final static String	NAME			= "name";
	public static final String	CMD_PATH		= "cmd.path";
	public static final String	CMD_INIT		= "cmd.init";
	public static final String	CMD_AFTER_PUT	= "cmd.after.put";
	public static final String	CMD_REFRESH		= "cmd.refresh";
	public static final String	CMD_BEFORE_PUT	= "cmd.before.put";
	public static final String	CMD_ABORT_PUT	= "cmd.abort.put";
	public static final String	CMD_SHELL		= "cmd.shell";
	static final PutOptions		DEFAULTOPTIONS	= new PutOptions();

	String						before;
	String						refresh;
	String						after;
	String						path;
	String						init;
	String						abort;
	String						shell;

	File[]						EMPTY_FILES		= new File[0];
	protected File				root;
	Registry					registry;
	boolean						canWrite		= true;
	Pattern						REPO_FILE		= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+|latest)\\.(jar|lib)");
	Reporter					reporter;
	boolean						dirty;
	String						name;
	boolean						inited;

	public FileRepo() {}

	public FileRepo(String name, File location, boolean canWrite) {
		this.name = name;
		this.root = location;
		this.canWrite = canWrite;
	}

	protected void init() throws Exception {
		if (inited)
			return;

		inited = true;
		if (!getRoot().isDirectory()) {
			getRoot().mkdirs();
		}
		exec(init, null);
	}

	public void setProperties(Map<String,String> map) {
		String location = map.get(LOCATION);
		if (location == null)
			throw new IllegalArgumentException("Location must be set on a FileRepo plugin");

		root = IO.getFile(IO.home, location);

		String readonly = map.get(READONLY);
		if (readonly != null && Boolean.valueOf(readonly).booleanValue())
			canWrite = false;

		name = map.get(NAME);
		before = map.get(CMD_BEFORE_PUT);
		refresh = map.get(CMD_REFRESH);
		after = map.get(CMD_AFTER_PUT);
		init = map.get(CMD_INIT);
		path = map.get(CMD_PATH);
		abort = map.get(CMD_ABORT_PUT);
		shell = map.get(CMD_SHELL);
	}

	/**
	 * Get a list of URLs to bundles that are constrained by the bsn and
	 * versionRange.
	 */
	private File[] get(String bsn, String versionRange) throws Exception {
		init();

		// If the version is set to project, we assume it is not
		// for us. A project repo will then get it.
		if (versionRange != null && versionRange.equals("project"))
			return null;

		//
		// Check if the entry exists
		//
		File f = new File(root, bsn);
		if (!f.isDirectory())
			return null;

		//
		// The version range we are looking for can
		// be null (for all) or a version range.
		//
		VersionRange range;
		if (versionRange == null || versionRange.equals("latest")) {
			range = new VersionRange("0");
		} else
			range = new VersionRange(versionRange);

		//
		// Iterator over all the versions for this BSN.
		// Create a sorted map over the version as key
		// and the file as URL as value. Only versions
		// that match the desired range are included in
		// this list.
		//
		File instances[] = f.listFiles();
		SortedMap<Version,File> versions = new TreeMap<Version,File>();
		for (int i = 0; i < instances.length; i++) {
			Matcher m = REPO_FILE.matcher(instances[i].getName());
			if (m.matches() && m.group(1).equals(bsn)) {
				String versionString = m.group(2);
				Version version;
				if (versionString.equals("latest"))
					version = new Version(Integer.MAX_VALUE);
				else
					version = new Version(versionString);

				if (range.includes(version) || versionString.equals(versionRange))
					versions.put(version, instances[i]);
			}
		}

		File[] files = versions.values().toArray(EMPTY_FILES);
		if ("latest".equals(versionRange) && files.length > 0) {
			return new File[] {
				files[files.length - 1]
			};
		}
		return files;
	}

	public boolean canWrite() {
		return canWrite;
	}

	protected PutResult putArtifact(File tmpFile, PutOptions options) throws Exception {
		assert (tmpFile != null);
		assert (options != null);

		Jar jar = null;
		try {
			dirty = true;

			jar = new Jar(tmpFile);

			Manifest manifest = jar.getManifest();
			if (manifest == null)
				throw new IllegalArgumentException("No manifest in JAR: " + jar);

			String bsn = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_SYMBOLICNAME);
			if (bsn == null)
				throw new IllegalArgumentException("No Bundle SymbolicName set");

			Parameters b = Processor.parseHeader(bsn, null);
			if (b.size() != 1)
				throw new IllegalArgumentException("Multiple bsn's specified " + b);

			for (String key : b.keySet()) {
				bsn = key;
				if (!Verifier.SYMBOLICNAME.matcher(bsn).matches())
					throw new IllegalArgumentException("Bundle SymbolicName has wrong format: " + bsn);
			}

			String versionString = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_VERSION);
			Version version;
			if (versionString == null)
				version = new Version();
			else
				version = new Version(versionString);

			if (reporter != null)
				reporter.trace("bsn=%s version=%s", bsn, version);

			File dir = new File(root, bsn);
			if (!dir.exists() && !dir.mkdirs()) {
				throw new IOException("Could not create directory " + dir);
			}
			String fName = bsn + "-" + version.getWithoutQualifier() + ".jar";
			File file = new File(dir, fName);

			boolean renamed = false;
			PutResult result = new PutResult();

			if (reporter != null)
				reporter.trace("updating %s ", file.getAbsolutePath());

			IO.delete(file);
			IO.rename(tmpFile, file);

			renamed = true;
			result.artifact = file.toURI();

			if (reporter != null)
				reporter.progress(-1, "updated " + file.getAbsolutePath());

			fireBundleAdded(jar, file);

			// Execute the after command
			exec(after, file);

			File latest = new File(dir, bsn + "-latest.jar");
			boolean latestExists = latest.exists() && latest.isFile();
			boolean latestIsOlder = latestExists && (latest.lastModified() < jar.lastModified());
			if ((options.createLatest && !latestExists) || latestIsOlder) {
				if (latestExists) {
					IO.delete(latest);
				}
				if (!renamed) {
					IO.rename(tmpFile, latest);
				} else {
					IO.copy(file, latest);
				}
				result.latest = latest.toURI();
			}

			return result;
		}
		finally {
			if (jar != null) {
				jar.close();
			}
		}
	}
{'fraction_non_alphanumeric': 0.13280022847351136, 'fraction_numerical': 0.0019277452520348422, 'mean_word_length': 3.325818406423718, 'pattern_counts': {'":': 0, '<': 14, '<?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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7316065', 'n_tokens_mistral': 5292, 'n_tokens_neox': 4506, 'n_words': 1261}