/* Copyright (c) 2014 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Gabriel Roldan (Boundless) - initial implementation */ package org.locationtech.geogig.cli.test.functional.general; import static org.junit.Assert.assertNotNull; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.lines1; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.lines2; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.lines3; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.points1; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.points1_FTmodified; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.points2; import static org.locationtech.geogig.cli.test.functional.general.TestFeatures.points3; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.List; import jline.UnsupportedTerminal; import jline.console.ConsoleReader; import org.junit.rules.TemporaryFolder; import org.locationtech.geogig.api.Context; import org.locationtech.geogig.api.ContextBuilder; import org.locationtech.geogig.api.GeoGIG; import org.locationtech.geogig.api.GlobalContextBuilder; import org.locationtech.geogig.api.Node; import org.locationtech.geogig.api.ObjectId; import org.locationtech.geogig.api.Platform; import org.locationtech.geogig.api.TestPlatform; import org.locationtech.geogig.cli.GeogigCLI; import org.locationtech.geogig.repository.Hints; import org.locationtech.geogig.repository.Repository; import org.locationtech.geogig.repository.WorkingTree; import org.opengis.feature.Feature; import org.opengis.feature.type.Name; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.io.CharSource; /** */ public class GlobalState { public static TemporaryFolder tempFolder; /** * {@link GeogigCLI#execute(String...)} exit code, upadted every time a {@link #runCommand * command is ran} */ public static int exitCode; /** * A platform to set the current working directory and the user home directory. * <p> * Note this platform is NOT the same than used by the created GeoGIG instances. They'll instead * use a copy of it (as per CLITestInjectorBuilder.build()), in order for the platform not to be * shared by multiple geogig instances open (like when working with remotes) and get them * confused on what their respective working dir is. So whenever this platform's working dir is * changed, setupGeogig() should be called for a new GeogigCLI to be created on the current * working dir, if need be. */ public static TestPlatform platform; public static File remoteRepo; public static ByteArrayInputStream stdIn; public static ByteArrayOutputStream stdOut; public static GeogigCLI geogigCLI; public static ConsoleReader consoleReader; public static void setUpDirectories() throws IOException { File homeDirectory = tempFolder.newFolder("fakeHomeDir").getCanonicalFile(); File currentDirectory = tempFolder.newFolder("testrepo").getCanonicalFile(); if (GlobalState.platform == null) { GlobalState.platform = new TestPlatform(currentDirectory, homeDirectory); } else { GlobalState.platform.setWorkingDir(currentDirectory); GlobalState.platform.setUserHome(homeDirectory); } } public static void setupGeogig() throws Exception { assertNotNull(platform); stdIn = new ByteArrayInputStream(new byte[0]); stdOut = new ByteArrayOutputStream(); if (GlobalState.consoleReader != null) { GlobalState.consoleReader.shutdown(); } // GlobalState.consoleReader = new ConsoleReader(stdIn, // new TeeOutputStream(stdOut, System.err), new UnsupportedTerminal()); GlobalState.consoleReader = new ConsoleReader(stdIn, stdOut, new UnsupportedTerminal()); ContextBuilder injectorBuilder = new CLITestContextBuilder(platform); Context injector = injectorBuilder.build(); if (geogigCLI != null) { geogigCLI.close(); } geogigCLI = new GeogigCLI(GlobalState.consoleReader); GlobalContextBuilder.builder = injectorBuilder; Platform platform = injector.platform(); geogigCLI.setPlatform(platform); geogigCLI.tryConfigureLogging(); } /** * Runs the given command with its arguments and returns the command output as a list of * strings, one per line. */ public static List<String> runAndParseCommand(String... command) throws Exception { return runAndParseCommand(false, command); } public static List<String> runAndParseCommand(boolean failFast, String... command) throws Exception { runCommand(failFast, command); CharSource reader = CharSource.wrap(stdOut.toString(Charsets.UTF_8.name())); ImmutableList<String> lines = reader.readLines(); return lines; } /** * @param commandAndArgs the command and its arguments. This method is dumb, be careful of not * using arguments that shouldn't be split on a space (like "commit -m 'separate words') */ public static void runCommand(String commandAndArgs) throws Exception { runCommand(false, commandAndArgs); } public static void runCommand(boolean failFast, String commandAndArgs) throws Exception { runCommand(failFast, commandAndArgs.split(" ")); } /** * runs the command, does not fail fast, check {@link GlobalState#exitCode} for the exit code * and {@link GeogigCLI#exception} for any caught exception */ public static void runCommand(String... command) throws Exception { runCommand(false, command); } public static void runCommand(boolean failFast, String... command) throws Exception { assertNotNull(geogigCLI); stdOut.reset(); exitCode = geogigCLI.execute(command); if (failFast && geogigCLI.exception != null) { Exception exception = geogigCLI.exception; throw exception; } } public static void insertFeatures() throws Exception { insert(points1); insert(points2); insert(points3); insert(lines1); insert(lines2); insert(lines3); } public static void insertAndAddFeatures() throws Exception { insertAndAdd(points1); insertAndAdd(points2); insertAndAdd(points3); insertAndAdd(lines1); insertAndAdd(lines2); insertAndAdd(lines3); } public static void deleteAndReplaceFeatureType() throws Exception { GeoGIG geogig = geogigCLI.newGeoGIG(); try { final WorkingTree workTree = geogig.getRepository().workingTree(); workTree.delete(points1.getType().getName()); Name name = points1_FTmodified.getType().getName(); String parentPath = name.getLocalPart(); workTree.insert(parentPath, points1_FTmodified); } finally { geogig.close(); } } /** * Inserts the Feature to the index and stages it to be committed. */ public static ObjectId insertAndAdd(Feature f) throws Exception { ObjectId objectId = insert(f); runCommand(true, "add"); return objectId; } /** * Inserts the feature to the index but does not stages it to be committed */ public static ObjectId insert(Feature f) throws Exception { return insert(new Feature[] { f }).get(0); } public static List<ObjectId> insertAndAdd(Feature... features) throws Exception { List<ObjectId> ids = insert(features); geogigCLI.execute("add"); return ids; } public static List<ObjectId> insert(Feature... features) throws Exception { geogigCLI.close(); GeoGIG geogig = geogigCLI.newGeoGIG(Hints.readWrite()); Preconditions.checkNotNull(geogig); List<ObjectId> ids = Lists.newArrayListWithCapacity(features.length); try { Repository repository = geogig.getRepository(); final WorkingTree workTree = repository.workingTree(); for (Feature f : features) { Name name = f.getType().getName(); String parentPath = name.getLocalPart(); Node ref = workTree.insert(parentPath, f); ObjectId objectId = ref.getObjectId(); ids.add(objectId); } } finally { geogig.close(); } return ids; } /** * Deletes a feature from the index * * @param f * @return * @throws Exception */ public static boolean deleteAndAdd(Feature f) throws Exception { boolean existed = delete(f); if (existed) { runCommand(true, "add"); } return existed; } public static boolean delete(Feature f) throws Exception { GeoGIG geogig = geogigCLI.newGeoGIG(); try { final WorkingTree workTree = geogig.getRepository().workingTree(); Name name = f.getType().getName(); String localPart = name.getLocalPart(); String id = f.getIdentifier().getID(); boolean existed = workTree.delete(localPart, id); return existed; } finally { geogig.close(); } } }