From 6b18b0761b726fd9aef1ebcc21b760378f7d4b5c Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Mon, 16 Jun 2014 17:36:12 -0400
Subject: [PATCH] Merge release 1.6.0

---
 src/main/java/com/gitblit/MigrateTickets.java |  256 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 256 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/gitblit/MigrateTickets.java b/src/main/java/com/gitblit/MigrateTickets.java
new file mode 100644
index 0000000..ad1c63e
--- /dev/null
+++ b/src/main/java/com/gitblit/MigrateTickets.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+import com.gitblit.manager.IRepositoryManager;
+import com.gitblit.manager.IRuntimeManager;
+import com.gitblit.manager.RepositoryManager;
+import com.gitblit.manager.RuntimeManager;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.TicketModel;
+import com.gitblit.models.TicketModel.Change;
+import com.gitblit.tickets.BranchTicketService;
+import com.gitblit.tickets.FileTicketService;
+import com.gitblit.tickets.ITicketService;
+import com.gitblit.tickets.RedisTicketService;
+import com.gitblit.utils.StringUtils;
+
+/**
+ * A command-line tool to move all tickets from one ticket service to another.
+ *
+ * @author James Moger
+ *
+ */
+public class MigrateTickets {
+
+	public static void main(String... args) {
+		MigrateTickets migrate = new MigrateTickets();
+
+		// filter out the baseFolder parameter
+		List<String> filtered = new ArrayList<String>();
+		String folder = "data";
+		for (int i = 0; i < args.length; i++) {
+			String arg = args[i];
+			if (arg.equals("--baseFolder")) {
+				if (i + 1 == args.length) {
+					System.out.println("Invalid --baseFolder parameter!");
+					System.exit(-1);
+				} else if (!".".equals(args[i + 1])) {
+					folder = args[i + 1];
+				}
+				i = i + 1;
+			} else {
+				filtered.add(arg);
+			}
+		}
+
+		Params.baseFolder = folder;
+		Params params = new Params();
+		CmdLineParser parser = new CmdLineParser(params);
+		try {
+			parser.parseArgument(filtered);
+			if (params.help) {
+				migrate.usage(parser, null);
+				return;
+			}
+		} catch (CmdLineException t) {
+			migrate.usage(parser, t);
+			return;
+		}
+
+		// load the settings
+		FileSettings settings = params.FILESETTINGS;
+		if (!StringUtils.isEmpty(params.settingsfile)) {
+			if (new File(params.settingsfile).exists()) {
+				settings = new FileSettings(params.settingsfile);
+			}
+		}
+
+		// migrate tickets
+		migrate.migrate(new File(Params.baseFolder), settings, params.outputServiceName);
+		System.exit(0);
+	}
+
+	/**
+	 * Display the command line usage of MigrateTickets.
+	 *
+	 * @param parser
+	 * @param t
+	 */
+	protected final void usage(CmdLineParser parser, CmdLineException t) {
+		System.out.println(Constants.BORDER);
+		System.out.println(Constants.getGitBlitVersion());
+		System.out.println(Constants.BORDER);
+		System.out.println();
+		if (t != null) {
+			System.out.println(t.getMessage());
+			System.out.println();
+		}
+		if (parser != null) {
+			parser.printUsage(System.out);
+			System.out
+					.println("\nExample:\n  java -gitblit.jar com.gitblit.MigrateTickets com.gitblit.tickets.RedisTicketService --baseFolder c:\\gitblit-data");
+		}
+		System.exit(0);
+	}
+
+	/**
+	 * Migrate all tickets
+	 *
+	 * @param baseFolder
+	 * @param settings
+	 * @param outputServiceName
+	 */
+	protected void migrate(File baseFolder, IStoredSettings settings, String outputServiceName) {
+		// disable some services
+		settings.overrideSetting(Keys.web.allowLuceneIndexing, false);
+		settings.overrideSetting(Keys.git.enableGarbageCollection, false);
+		settings.overrideSetting(Keys.git.enableMirroring, false);
+		settings.overrideSetting(Keys.web.activityCacheDays, 0);
+		settings.overrideSetting(ITicketService.SETTING_UPDATE_DIFFSTATS, false);
+
+		IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start();
+		IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start();
+
+		String inputServiceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName());
+		if (StringUtils.isEmpty(inputServiceName)) {
+			System.err.println(MessageFormat.format("Please define a ticket service in \"{0}\"", Keys.tickets.service));
+			System.exit(1);
+		}
+
+		ITicketService inputService = null;
+		ITicketService outputService = null;
+		try {
+			inputService = getService(inputServiceName, runtimeManager, repositoryManager);
+			outputService = getService(outputServiceName, runtimeManager, repositoryManager);
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+
+		if (!inputService.isReady()) {
+			System.err.println(String.format("%s INPUT service is not ready, check config.", inputService.getClass().getSimpleName()));
+			System.exit(1);
+		}
+
+		if (!outputService.isReady()) {
+			System.err.println(String.format("%s OUTPUT service is not ready, check config.", outputService.getClass().getSimpleName()));
+			System.exit(1);
+		}
+
+		// migrate tickets
+		long start = System.nanoTime();
+		long totalTickets = 0;
+		long totalChanges = 0;
+		for (RepositoryModel repository : repositoryManager.getRepositoryModels(null)) {
+			Set<Long> ids = inputService.getIds(repository);
+			if (ids == null || ids.isEmpty()) {
+				// nothing to migrate
+				continue;
+			}
+
+			// delete any tickets we may have in the output ticket service
+			outputService.deleteAll(repository);
+
+			for (long id : ids) {
+				List<Change> journal = inputService.getJournal(repository, id);
+				if (journal == null || journal.size() == 0) {
+					continue;
+				}
+				TicketModel ticket = outputService.createTicket(repository, id, journal.get(0));
+				if (ticket == null) {
+					System.err.println(String.format("Failed to migrate %s #%s", repository.name, id));
+					System.exit(1);
+				}
+				totalTickets++;
+				System.out.println(String.format("%s #%s: %s", repository.name, ticket.number, ticket.title));
+				for (int i = 1; i < journal.size(); i++) {
+					TicketModel updated = outputService.updateTicket(repository, ticket.number, journal.get(i));
+					if (updated != null) {
+						System.out.println(String.format("   applied change %d", i));
+						totalChanges++;
+					} else {
+						System.err.println(String.format("Failed to apply change %d:\n%s", i, journal.get(i)));
+						System.exit(1);
+					}
+				}
+			}
+		}
+
+		inputService.stop();
+		outputService.stop();
+
+		repositoryManager.stop();
+		runtimeManager.stop();
+
+		long end = System.nanoTime();
+
+		System.out.println(String.format("Migrated %d tickets composed of %d journal entries in %d seconds",
+				totalTickets, totalTickets + totalChanges, TimeUnit.NANOSECONDS.toSeconds(end - start)));
+	}
+
+	protected ITicketService getService(String serviceName, IRuntimeManager runtimeManager, IRepositoryManager repositoryManager) throws Exception {
+		ITicketService service = null;
+		Class<?> serviceClass = Class.forName(serviceName);
+		if (RedisTicketService.class.isAssignableFrom(serviceClass)) {
+			// Redis ticket service
+			service = new RedisTicketService(runtimeManager, null, null, null, repositoryManager).start();
+		} else if (BranchTicketService.class.isAssignableFrom(serviceClass)) {
+			// Branch ticket service
+			service = new BranchTicketService(runtimeManager, null, null, null, repositoryManager).start();
+		} else if (FileTicketService.class.isAssignableFrom(serviceClass)) {
+			// File ticket service
+			service = new FileTicketService(runtimeManager, null, null, null, repositoryManager).start();
+		} else {
+			System.err.println("Unknown ticket service " + serviceName);
+		}
+		return service;
+	}
+
+	/**
+	 * Parameters.
+	 */
+	public static class Params {
+
+		public static String baseFolder;
+
+		@Option(name = "--help", aliases = { "-h"}, usage = "Show this help")
+		public Boolean help = false;
+
+		private final FileSettings FILESETTINGS = new FileSettings(new File(baseFolder, Constants.PROPERTIES_FILE).getAbsolutePath());
+
+		@Option(name = "--repositoriesFolder", usage = "Git Repositories Folder", metaVar = "PATH")
+		public String repositoriesFolder = FILESETTINGS.getString(Keys.git.repositoriesFolder, "git");
+
+		@Option(name = "--settings", usage = "Path to alternative settings", metaVar = "FILE")
+		public String settingsfile;
+
+		@Argument(index = 0, required = true, metaVar = "OUTPUTSERVICE", usage = "The destination/output ticket service")
+		public String outputServiceName;
+	}
+}

--
Gitblit v1.9.1