mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ICS: fix broken copyLocalConfig again and test
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
<root>
|
||||
<item name='java.nio.file.FileSystem java.nio.file.Path getPath(java.lang.String, java.lang.String...)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='java.nio.file.Path java.nio.file.Path getParent()'>
|
||||
<annotation name='org.jetbrains.annotations.Nullable'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -20,11 +20,11 @@ import org.jetbrains.io.MessageDecoder
|
||||
import org.jetbrains.io.NettyUtil
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
import java.util.UUID
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// we don't handle String in efficient way - because we want to test readContent/readChars also
|
||||
public class BinaryRequestHandlerTest {
|
||||
internal class BinaryRequestHandlerTest {
|
||||
companion object {
|
||||
@ClassRule val projectRule = ProjectRule()
|
||||
}
|
||||
@@ -47,13 +47,13 @@ public class BinaryRequestHandlerTest {
|
||||
}
|
||||
})
|
||||
|
||||
val port = BuiltInServerManager.getInstance().waitForStart().getPort()
|
||||
val port = BuiltInServerManager.getInstance().waitForStart().port
|
||||
val channel = bootstrap.connect(NetUtils.getLoopbackAddress(), port).syncUninterruptibly().channel()
|
||||
val buffer = channel.alloc().buffer()
|
||||
buffer.writeByte('C'.toInt())
|
||||
buffer.writeByte('H'.toInt())
|
||||
buffer.writeLong(MyBinaryRequestHandler.ID.getMostSignificantBits())
|
||||
buffer.writeLong(MyBinaryRequestHandler.ID.getLeastSignificantBits())
|
||||
buffer.writeLong(MyBinaryRequestHandler.ID.mostSignificantBits)
|
||||
buffer.writeLong(MyBinaryRequestHandler.ID.leastSignificantBits)
|
||||
|
||||
val message = Unpooled.copiedBuffer(text, CharsetUtil.UTF_8)
|
||||
buffer.writeShort(message.readableBytes())
|
||||
@@ -67,7 +67,7 @@ public class BinaryRequestHandlerTest {
|
||||
}
|
||||
})
|
||||
|
||||
if (result.getState() == Promise.State.PENDING) {
|
||||
if (result.state == Promise.State.PENDING) {
|
||||
val semaphore = Semaphore()
|
||||
semaphore.down()
|
||||
result.processed { semaphore.up() }
|
||||
|
||||
@@ -32,9 +32,9 @@ import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import org.jdom.Element
|
||||
|
||||
class ApplicationPathMacroManager : BasePathMacroManager(null)
|
||||
private class ApplicationPathMacroManager : BasePathMacroManager(null)
|
||||
|
||||
class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager) : ComponentStoreImpl() {
|
||||
class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager? = null) : ComponentStoreImpl() {
|
||||
override val storageManager = ApplicationStorageManager(application, pathMacroManager)
|
||||
|
||||
// number of app components require some state, so, we load default state in test mode
|
||||
@@ -42,8 +42,9 @@ class ApplicationStoreImpl(private val application: Application, pathMacroManage
|
||||
get() = if (application.isUnitTestMode) StateLoadPolicy.LOAD_ONLY_DEFAULT else StateLoadPolicy.LOAD
|
||||
|
||||
override fun setPath(path: String) {
|
||||
storageManager.addMacro(ROOT_CONFIG, path)
|
||||
// app config must be first, because collapseMacros collapse from fist to last, so, at first we must replace APP_CONFIG because it overlaps ROOT_CONFIG value
|
||||
storageManager.addMacro(StoragePathMacros.APP_CONFIG, "$path/${ApplicationStorageManager.FILE_STORAGE_DIR}")
|
||||
storageManager.addMacro(ROOT_CONFIG, path)
|
||||
|
||||
val configDir = LocalFileSystem.getInstance().refreshAndFindFileByPath(path)
|
||||
if (configDir != null) {
|
||||
@@ -110,9 +111,9 @@ class ApplicationStorageManager(private val application: Application, pathMacroM
|
||||
return path
|
||||
}
|
||||
|
||||
override fun expandNormalizedPath(path: String): String {
|
||||
override fun expandMacros(path: String): String {
|
||||
if (path[0] == '$') {
|
||||
return super.expandNormalizedPath(path)
|
||||
return super.expandMacros(path)
|
||||
}
|
||||
else {
|
||||
return "${expandMacro(StoragePathMacros.APP_CONFIG)}/$path"
|
||||
|
||||
@@ -73,8 +73,6 @@ internal class DefaultProjectStoreImpl(override val project: ProjectImpl, privat
|
||||
|
||||
override fun expandMacros(file: String) = throw UnsupportedOperationException("Method expandMacros not implemented in " + javaClass)
|
||||
|
||||
override fun collapseMacros(path: String) = throw UnsupportedOperationException("Method collapseMacros not implemented in " + javaClass)
|
||||
|
||||
override fun getOldStorage(component: Any, componentName: String, operation: StateStorageOperation) = storage
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ class ProjectStateStorageManager(macroSubstitutor: TrackingPathMacroSubstitutor,
|
||||
return path
|
||||
}
|
||||
|
||||
override fun expandNormalizedPath(path: String): String {
|
||||
override fun expandMacros(path: String): String {
|
||||
if (path[0] == '$') {
|
||||
return super.expandNormalizedPath(path)
|
||||
return super.expandMacros(path)
|
||||
}
|
||||
else {
|
||||
return "${expandMacro(StoragePathMacros.PROJECT_CONFIG_DIR)}/$path"
|
||||
|
||||
@@ -29,9 +29,9 @@ import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.lang.CompoundRuntimeException
|
||||
import java.io.File
|
||||
|
||||
val ROOT_CONFIG: String = "\$ROOT_CONFIG$"
|
||||
val ROOT_CONFIG = "\$ROOT_CONFIG$"
|
||||
|
||||
public abstract class SchemeManagerFactoryBase : SchemesManagerFactory(), SettingsSavingComponent {
|
||||
sealed class SchemeManagerFactoryBase : SchemesManagerFactory(), SettingsSavingComponent {
|
||||
private val managers = ContainerUtil.createLockFreeCopyOnWriteList<SchemeManagerImpl<Scheme, ExternalizableScheme>>()
|
||||
|
||||
abstract val componentManager: ComponentManager
|
||||
@@ -85,27 +85,27 @@ public abstract class SchemeManagerFactoryBase : SchemesManagerFactory(), Settin
|
||||
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
}
|
||||
}
|
||||
|
||||
private class ApplicationSchemeManagerFactory : SchemeManagerFactoryBase() {
|
||||
override val componentManager: ComponentManager
|
||||
get() = ApplicationManager.getApplication()
|
||||
private class ApplicationSchemeManagerFactory : SchemeManagerFactoryBase() {
|
||||
override val componentManager: ComponentManager
|
||||
get() = ApplicationManager.getApplication()
|
||||
|
||||
override fun checkPath(originalPath: String): String {
|
||||
var path = super.checkPath(originalPath)
|
||||
if (path.startsWith(ROOT_CONFIG)) {
|
||||
path = path.substring(ROOT_CONFIG.length() + 1)
|
||||
val message = "Path must not contains ROOT_CONFIG macro, corrected: $path"
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) throw AssertionError(message) else LOG.warn(message)
|
||||
override fun checkPath(originalPath: String): String {
|
||||
var path = super.checkPath(originalPath)
|
||||
if (path.startsWith(ROOT_CONFIG)) {
|
||||
path = path.substring(ROOT_CONFIG.length() + 1)
|
||||
val message = "Path must not contains ROOT_CONFIG macro, corrected: $path"
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) throw AssertionError(message) else LOG.warn(message)
|
||||
}
|
||||
return path
|
||||
}
|
||||
return path
|
||||
|
||||
override fun pathToFile(path: String, storageManager: StateStorageManager) = File(storageManager.expandMacros("$ROOT_CONFIG/$path"))
|
||||
}
|
||||
|
||||
override fun pathToFile(path: String, storageManager: StateStorageManager) = File(storageManager.expandMacros("$ROOT_CONFIG/$path"))
|
||||
}
|
||||
private class ProjectSchemeManagerFactory(private val project: Project) : SchemeManagerFactoryBase() {
|
||||
override val componentManager = project
|
||||
|
||||
private class ProjectSchemeManagerFactory(private val project: Project) : SchemeManagerFactoryBase() {
|
||||
override val componentManager = project
|
||||
|
||||
override fun pathToFile(path: String, storageManager: StateStorageManager) = File(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
|
||||
override fun pathToFile(path: String, storageManager: StateStorageManager) = File(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
private val storageLock = ReentrantLock()
|
||||
private val storages = THashMap<String, StateStorage>()
|
||||
|
||||
public var streamProvider: StreamProvider? = null
|
||||
var streamProvider: StreamProvider? = null
|
||||
|
||||
// access under storageLock
|
||||
private var isUseVfsListener = if (componentManager == null) ThreeState.NO else ThreeState.UNSURE // unsure because depends on stream provider state
|
||||
@@ -138,22 +138,16 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
return if (path.endsWith('/')) path.substring(0, path.length() - 1) else path
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path Must be normalized (see normalizeFileSpec})
|
||||
* @return System-independent path
|
||||
*/
|
||||
open fun expandNormalizedPath(path: String): String = expandMacros(path)
|
||||
|
||||
fun getOrCreateStorage(fileSpec: String,
|
||||
fun getOrCreateStorage(collapsedPath: String,
|
||||
roamingType: RoamingType = RoamingType.DEFAULT,
|
||||
storageClass: Class<out StateStorage> = StateStorage::class.java,
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") @SuppressWarnings("deprecation") stateSplitter: Class<out StateSplitter> = StateSplitterEx::class.java): StateStorage {
|
||||
val collapsedPath = normalizeFileSpec(fileSpec)
|
||||
val key = if (storageClass == StateStorage::class.java) collapsedPath else storageClass.name
|
||||
val normalizedCollapsedPath = normalizeFileSpec(collapsedPath)
|
||||
val key = if (storageClass == StateStorage::class.java) normalizedCollapsedPath else storageClass.name
|
||||
storageLock.withLock {
|
||||
var storage = storages.get(key)
|
||||
if (storage == null) {
|
||||
storage = createStateStorage(storageClass, collapsedPath, roamingType, stateSplitter)
|
||||
storage = createStateStorage(storageClass, normalizedCollapsedPath, roamingType, stateSplitter)
|
||||
storages.put(key, storage)
|
||||
}
|
||||
return storage
|
||||
@@ -197,7 +191,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
isUseVfsListener = ThreeState.fromBoolean(streamProvider == null || !streamProvider!!.enabled)
|
||||
}
|
||||
|
||||
val filePath = expandNormalizedPath(collapsedPath)
|
||||
val filePath = expandMacros(collapsedPath)
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
if (stateSplitter != StateSplitter::class.java && stateSplitter != StateSplitterEx::class.java) {
|
||||
val storage = MyDirectoryStorage(this, File(filePath), ReflectionUtil.newInstance(stateSplitter))
|
||||
@@ -282,7 +276,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
try {
|
||||
if (virtualFileTracker != null) {
|
||||
storages.forEachEntry({ collapsedPath, storage ->
|
||||
virtualFileTracker.remove(expandNormalizedPath(collapsedPath))
|
||||
virtualFileTracker.remove(expandMacros(collapsedPath))
|
||||
true
|
||||
})
|
||||
}
|
||||
@@ -295,7 +289,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
|
||||
protected open fun getMacroSubstitutor(fileSpec: String): TrackingPathMacroSubstitutor? = pathMacroSubstitutor
|
||||
|
||||
override final fun expandMacros(path: String): String {
|
||||
override fun expandMacros(path: String): String {
|
||||
// replacement can contains $ (php tests), so, this check must be performed before expand
|
||||
val matcher = MACRO_PATTERN.matcher(path)
|
||||
matcherLoop@
|
||||
@@ -326,17 +320,17 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
throw IllegalArgumentException("Unknown macro $macro")
|
||||
}
|
||||
|
||||
override final fun collapseMacros(path: String): String {
|
||||
fun collapseMacros(path: String): String {
|
||||
var result = path
|
||||
for ((key, value) in macros) {
|
||||
result = StringUtil.replace(result, value, key)
|
||||
}
|
||||
return result
|
||||
return normalizeFileSpec(result)
|
||||
}
|
||||
|
||||
override fun startExternalization() = StateStorageManagerExternalizationSession(this)
|
||||
|
||||
class StateStorageManagerExternalizationSession(protected val storageManager: StateStorageManagerImpl) : StateStorageManager.ExternalizationSession {
|
||||
private class StateStorageManagerExternalizationSession(private val storageManager: StateStorageManagerImpl) : StateStorageManager.ExternalizationSession {
|
||||
private val sessions = LinkedHashMap<StateStorage, StateStorage.ExternalizationSession>()
|
||||
|
||||
override fun setState(storageSpecs: Array<Storage>, component: Any, componentName: String, state: Any) {
|
||||
|
||||
@@ -67,7 +67,7 @@ internal class ApplicationStoreTest {
|
||||
component.foo = "newValue"
|
||||
componentStore.save(SmartList())
|
||||
|
||||
assertThat(streamProvider.data.get(RoamingType.DEFAULT)!!.get("new.xml")).isEqualTo("<application>\n" + " <component name=\"A\" foo=\"newValue\" />\n" + "</application>")
|
||||
assertThat(streamProvider.data.get(RoamingType.DEFAULT)!!.get("new.xml")).isEqualTo("<application>\n <component name=\"A\" foo=\"newValue\" />\n</application>")
|
||||
}
|
||||
|
||||
@Test fun `load from stream provider`() {
|
||||
@@ -83,7 +83,7 @@ internal class ApplicationStoreTest {
|
||||
componentStore.initComponent(component, false)
|
||||
assertThat(component.foo).isEqualTo("newValue")
|
||||
|
||||
assertThat(Paths.get(componentStore.storageManager.expandNormalizedPath(fileSpec))).isRegularFile()
|
||||
assertThat(Paths.get(componentStore.storageManager.expandMacros(fileSpec))).isRegularFile()
|
||||
}
|
||||
|
||||
@Test fun `remove deprecated storage on write`() {
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class StorageManagerTest {
|
||||
internal class StorageManagerTest {
|
||||
companion object {
|
||||
val MACRO = "\$MACRO1$"
|
||||
|
||||
@@ -36,27 +36,27 @@ class StorageManagerTest {
|
||||
|
||||
private var storageManager: StateStorageManagerImpl by Delegates.notNull()
|
||||
|
||||
public @Before fun setUp() {
|
||||
@Before fun setUp() {
|
||||
storageManager = StateStorageManagerImpl("foo")
|
||||
storageManager.addMacro(MACRO, "/temp/m1")
|
||||
}
|
||||
|
||||
public @Test fun createFileStateStorageMacroSubstituted() {
|
||||
@Test fun createFileStateStorageMacroSubstituted() {
|
||||
assertThat(storageManager.getOrCreateStorage("$MACRO/test.xml")).isNotNull()
|
||||
}
|
||||
|
||||
public @Test fun `collapse macro`() {
|
||||
@Test fun `collapse macro`() {
|
||||
assertThat(storageManager.collapseMacros("/temp/m1/foo")).isEqualTo("$MACRO/foo")
|
||||
assertThat(storageManager.collapseMacros("\\temp\\m1\\foo")).isEqualTo("\\temp\\m1\\foo")
|
||||
assertThat(storageManager.collapseMacros("\\temp\\m1\\foo")).isEqualTo("/temp/m1/foo")
|
||||
}
|
||||
|
||||
public @Test fun `add system-dependent macro`() {
|
||||
@Test fun `add system-dependent macro`() {
|
||||
val key = "\$INVALID$"
|
||||
val expansion = "\\temp"
|
||||
assertThatThrownBy({storageManager.addMacro(key, expansion) }).hasMessage("Macro $key set to system-dependent expansion $expansion")
|
||||
}
|
||||
|
||||
public @Test fun `create storage assertion thrown when unknown macro`() {
|
||||
@Test fun `create storage assertion thrown when unknown macro`() {
|
||||
try {
|
||||
storageManager.getOrCreateStorage("\$UNKNOWN_MACRO$/test.xml")
|
||||
TestCase.fail("Exception expected")
|
||||
@@ -66,7 +66,7 @@ class StorageManagerTest {
|
||||
}
|
||||
}
|
||||
|
||||
public @Test fun `create file storage macro substituted when expansion has$`() {
|
||||
@Test fun `create file storage macro substituted when expansion has$`() {
|
||||
storageManager.addMacro("\$DOLLAR_MACRO$", "/temp/d$")
|
||||
assertThat(storageManager.getOrCreateStorage("\$DOLLAR_MACRO$/test.xml")).isNotNull()
|
||||
}
|
||||
|
||||
@@ -161,7 +161,14 @@ public class ExportSettingsAction extends AnAction implements DumbAware {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(final boolean onlyExisting, final boolean computePresentableNames) {
|
||||
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(boolean onlyExisting, boolean computePresentableNames) {
|
||||
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
|
||||
StateStorageManager storageManager = ComponentsPackage.getStateStore(application).getStateStorageManager();
|
||||
return getExportableComponentsMap(onlyExisting, computePresentableNames, storageManager);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(final boolean onlyExisting, final boolean computePresentableNames, final @NotNull StateStorageManager storageManager) {
|
||||
@SuppressWarnings("deprecation")
|
||||
List<ExportableApplicationComponent> components1 = ComponentsPackage.getComponents(ApplicationManager.getApplication(), ExportableApplicationComponent.class);
|
||||
List<ExportableComponent> components2 = ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class);
|
||||
@@ -180,9 +187,7 @@ public class ExportSettingsAction extends AnAction implements DumbAware {
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
|
||||
final StateStorageManager storageManager = ComponentsPackage.getStateStore(application).getStateStorageManager();
|
||||
ServiceManagerImpl.processAllImplementationClasses(application, new PairProcessor<Class<?>, PluginDescriptor>() {
|
||||
ServiceManagerImpl.processAllImplementationClasses((ApplicationImpl)ApplicationManager.getApplication(), new PairProcessor<Class<?>, PluginDescriptor>() {
|
||||
@Override
|
||||
public boolean process(@NotNull Class<?> aClass, @Nullable PluginDescriptor pluginDescriptor) {
|
||||
State stateAnnotation = StoreUtil.getStateSpec(aClass);
|
||||
|
||||
-6
@@ -48,12 +48,6 @@ public interface StateStorageManager {
|
||||
@NotNull
|
||||
String expandMacros(@NotNull String path);
|
||||
|
||||
@NotNull
|
||||
/**
|
||||
* @param path System-independent path.
|
||||
*/
|
||||
String collapseMacros(@NotNull String path);
|
||||
|
||||
interface ExternalizationSession {
|
||||
void setState(@NotNull Storage[] storageSpecs, @NotNull Object component, @NotNull String componentName, @NotNull Object state);
|
||||
|
||||
|
||||
@@ -169,9 +169,9 @@
|
||||
serviceImplementation="com.intellij.execution.process.impl.OSProcessManagerImpl"/>
|
||||
|
||||
<applicationService serviceInterface="com.intellij.openapi.options.SchemesManagerFactory"
|
||||
serviceImplementation="com.intellij.configurationStore.ApplicationSchemeManagerFactory"/>
|
||||
serviceImplementation="com.intellij.configurationStore.SchemeManagerFactoryBase$ApplicationSchemeManagerFactory"/>
|
||||
<projectService serviceInterface="com.intellij.openapi.options.SchemesManagerFactory"
|
||||
serviceImplementation="com.intellij.configurationStore.ProjectSchemeManagerFactory"/>
|
||||
serviceImplementation="com.intellij.configurationStore.SchemeManagerFactoryBase$ProjectSchemeManagerFactory"/>
|
||||
|
||||
<applicationService serviceImplementation="com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager"/>
|
||||
<applicationService serviceInterface="com.intellij.openapi.editor.colors.TextAttributesKey$TextAttributeKeyDefaultsProvider"
|
||||
|
||||
@@ -26,17 +26,17 @@ import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.*
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import java.nio.file.attribute.FileTime
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
public class TemporaryDirectory : ExternalResource() {
|
||||
class TemporaryDirectory : ExternalResource() {
|
||||
private val paths = SmartList<Path>()
|
||||
|
||||
private var sanitizedName: String? = null
|
||||
private var sanitizedName: String by Delegates.notNull()
|
||||
|
||||
override fun apply(base: Statement, description: Description): Statement {
|
||||
sanitizedName = FileUtil.sanitizeFileName(description.getMethodName(), false)
|
||||
sanitizedName = FileUtil.sanitizeFileName(description.methodName, false)
|
||||
return super.apply(base, description)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class TemporaryDirectory : ExternalResource() {
|
||||
}
|
||||
|
||||
private fun generatePath(suffix: String?): Path {
|
||||
var fileName = sanitizedName!!
|
||||
var fileName = sanitizedName
|
||||
if (suffix != null) {
|
||||
fileName += "_$suffix"
|
||||
}
|
||||
@@ -93,65 +93,4 @@ public fun generateTemporaryPath(fileName: String?): Path {
|
||||
throw IOException("Cannot generate unique random path")
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
public fun Path.exists(): Boolean = Files.exists(this)
|
||||
|
||||
public fun Path.createDirectories(): Path = Files.createDirectories(this)
|
||||
|
||||
public fun Path.deleteRecursively(): Path = if (exists()) Files.walkFileTree(this, object : SimpleFileVisitor<Path>() {
|
||||
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||
Files.delete(file)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
|
||||
Files.delete(dir)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
}) else this
|
||||
|
||||
public fun Path.getLastModifiedTime(): FileTime? = Files.getLastModifiedTime(this)
|
||||
|
||||
public val Path.systemIndependentPath: String
|
||||
get() = toString().replace(File.separatorChar, '/')
|
||||
|
||||
public val Path.parentSystemIndependentPath: String
|
||||
get() = getParent()!!.toString().replace(File.separatorChar, '/')
|
||||
|
||||
public fun Path.readText(): String = Files.readAllBytes(this).toString(Charsets.UTF_8)
|
||||
|
||||
public fun VirtualFile.writeChild(relativePath: String, data: String): VirtualFile = VfsTestUtil.createFile(this, relativePath, data)
|
||||
|
||||
public fun Path.writeChild(relativePath: String, data: String): Path = writeChild(relativePath, data.toByteArray())
|
||||
|
||||
public fun Path.writeChild(relativePath: String, data: ByteArray): Path {
|
||||
val path = resolve(relativePath)
|
||||
path.getParent().createDirectories()
|
||||
return Files.write(path, data)
|
||||
}
|
||||
|
||||
public fun Path.isDirectory(): Boolean = Files.isDirectory(this)
|
||||
|
||||
public fun Path.isFile(): Boolean = Files.isRegularFile(this)
|
||||
|
||||
/**
|
||||
* Opposite to ugly Java, parent directories will be created
|
||||
*/
|
||||
public fun Path.createFile() {
|
||||
getParent()?.createDirectories()
|
||||
Files.createFile(this)
|
||||
}
|
||||
|
||||
public fun Path.refreshVfs() {
|
||||
LocalFileSystem.getInstance()?.let { fs ->
|
||||
// If a temp directory is reused from some previous test run, there might be cached children in its VFS. Ensure they're removed.
|
||||
val virtualFile = fs.findFileByPath(systemIndependentPath)
|
||||
if (virtualFile != null) {
|
||||
VfsUtil.markDirtyAndRefresh(false, true, true, virtualFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val VirtualFile.path: String
|
||||
get() = getPath()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.intellij.testFramework
|
||||
|
||||
import java.nio.file.FileSystem
|
||||
|
||||
fun FileSystem.file(path: String, data: ByteArray): FileSystem {
|
||||
getPath(path).write(data)
|
||||
return this
|
||||
}
|
||||
|
||||
fun FileSystem.file(path: String, data: String) = file(path, data.toByteArray())
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.intellij.testFramework
|
||||
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.FileVisitResult
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.SimpleFileVisitor
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import java.nio.file.attribute.FileTime
|
||||
|
||||
fun Path.exists(): Boolean = Files.exists(this)
|
||||
|
||||
fun Path.createDirectories(): Path = Files.createDirectories(this)
|
||||
|
||||
fun Path.deleteRecursively(): Path = if (exists()) Files.walkFileTree(this, object : SimpleFileVisitor<Path>() {
|
||||
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||
Files.delete(file)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
|
||||
Files.delete(dir)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
}) else this
|
||||
|
||||
fun Path.getLastModifiedTime(): FileTime? = Files.getLastModifiedTime(this)
|
||||
|
||||
val Path.systemIndependentPath: String
|
||||
get() = toString().replace(File.separatorChar, '/')
|
||||
|
||||
val Path.parentSystemIndependentPath: String
|
||||
get() = parent!!.toString().replace(File.separatorChar, '/')
|
||||
|
||||
fun Path.readText() = Files.readAllBytes(this).toString(Charsets.UTF_8)
|
||||
|
||||
fun VirtualFile.writeChild(relativePath: String, data: String) = VfsTestUtil.createFile(this, relativePath, data)
|
||||
|
||||
fun Path.writeChild(relativePath: String, data: ByteArray) = resolve(relativePath).write(data)
|
||||
|
||||
fun Path.writeChild(relativePath: String, data: String) = writeChild(relativePath, data.toByteArray())
|
||||
|
||||
fun Path.write(data: ByteArray): Path {
|
||||
parent?.createDirectories()
|
||||
return Files.write(this, data)
|
||||
}
|
||||
|
||||
fun Path.isDirectory() = Files.isDirectory(this)
|
||||
|
||||
fun Path.isFile() = Files.isRegularFile(this)
|
||||
|
||||
/**
|
||||
* Opposite to Java, parent directories will be created
|
||||
*/
|
||||
fun Path.createFile() {
|
||||
parent?.createDirectories()
|
||||
Files.createFile(this)
|
||||
}
|
||||
|
||||
fun Path.refreshVfs() {
|
||||
LocalFileSystem.getInstance()?.let { fs ->
|
||||
// If a temp directory is reused from some previous test run, there might be cached children in its VFS. Ensure they're removed.
|
||||
val virtualFile = fs.findFileByPath(systemIndependentPath)
|
||||
if (virtualFile != null) {
|
||||
VfsUtil.markDirtyAndRefresh(false, true, true, virtualFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -23,5 +23,17 @@
|
||||
<orderEntry type="module" module-name="util-tests" scope="TEST" />
|
||||
<orderEntry type="module" module-name="settings-repository" />
|
||||
<orderEntry type="library" scope="TEST" name="assertJ" level="project" />
|
||||
<orderEntry type="module-library">
|
||||
<library name="memoryfilesystem">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/dev/memoryfilesystem-0.6.7.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$MODULE_DIR$/lib/dev/memoryfilesystem-0.6.7-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module" module-name="test-framework-java8" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -34,7 +34,7 @@ import com.intellij.openapi.vcs.VcsNotifier
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier
|
||||
import java.util.concurrent.Future
|
||||
|
||||
class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
internal class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
private @Volatile var autoSyncFuture: Future<*>? = null
|
||||
|
||||
fun waitAutoSync(indicator: ProgressIndicator) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.settingsRepository
|
||||
|
||||
import com.intellij.configurationStore.ROOT_CONFIG
|
||||
import com.intellij.configurationStore.StateStorageManagerImpl
|
||||
import com.intellij.ide.actions.ExportSettingsAction
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
@@ -23,14 +24,14 @@ import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import java.io.File
|
||||
|
||||
fun copyLocalConfig() {
|
||||
val storageManager = ApplicationManager.getApplication()!!.stateStore.stateStorageManager as StateStorageManagerImpl
|
||||
fun copyLocalConfig(storageManager: StateStorageManagerImpl = ApplicationManager.getApplication()!!.stateStore.stateStorageManager as StateStorageManagerImpl) {
|
||||
val streamProvider = storageManager.streamProvider!! as IcsManager.IcsStreamProvider
|
||||
|
||||
val fileToComponents = ExportSettingsAction.getExportableComponentsMap(true, false)
|
||||
val fileToComponents = ExportSettingsAction.getExportableComponentsMap(true, false, storageManager)
|
||||
for (file in fileToComponents.keySet()) {
|
||||
val absolutePath = FileUtilRt.toSystemIndependentName(file.absolutePath)
|
||||
var fileSpec = storageManager.collapseMacros(absolutePath)
|
||||
LOG.assertTrue(!fileSpec.contains(ROOT_CONFIG))
|
||||
if (fileSpec.equals(absolutePath)) {
|
||||
// we have not experienced such problem yet, but we are just aware
|
||||
val canonicalPath = FileUtilRt.toSystemIndependentName(file.canonicalPath)
|
||||
|
||||
@@ -83,13 +83,19 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
|
||||
when (syncType) {
|
||||
SyncType.MERGE -> {
|
||||
updateResult = repositoryManager.pull(indicator)
|
||||
var doPush = true
|
||||
if (localRepositoryInitializer != null) {
|
||||
// must be performed only after initial pull, so, local changes will be relative to remote files
|
||||
localRepositoryInitializer()
|
||||
repositoryManager.commit(indicator)
|
||||
updateResult = updateResult.concat(repositoryManager.pull(indicator))
|
||||
if (!repositoryManager.commit(indicator, syncType) || repositoryManager.getAheadCommitsCount() == 0) {
|
||||
// avoid error during findRemoteRefUpdatesFor on push - if localRepositoryInitializer specified and nothing to commit (failed or just no files to commit (empty local configuration - no files)),
|
||||
// so, nothing to push
|
||||
doPush = false
|
||||
}
|
||||
}
|
||||
if (doPush) {
|
||||
repositoryManager.push(indicator)
|
||||
}
|
||||
repositoryManager.push(indicator)
|
||||
}
|
||||
SyncType.OVERWRITE_LOCAL -> {
|
||||
// we don't push - probably, repository will be modified/removed (user can do something, like undo) before any other next push activities (so, we don't want to disturb remote)
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
package org.jetbrains.settingsRepository.test
|
||||
|
||||
import com.intellij.configurationStore.ApplicationStoreImpl
|
||||
import com.intellij.configurationStore.write
|
||||
import com.intellij.mock.MockVirtualFileSystem
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vcs.merge.MergeSession
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
import com.intellij.testFramework.path
|
||||
import com.intellij.testFramework.file
|
||||
import com.intellij.testFramework.writeChild
|
||||
import com.intellij.util.PathUtilRt
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.eclipse.jgit.api.Git
|
||||
@@ -31,6 +33,7 @@ import org.jetbrains.jgit.dirCache.writePath
|
||||
import org.jetbrains.settingsRepository.CannotResolveConflictInTestMode
|
||||
import org.jetbrains.settingsRepository.SyncType
|
||||
import org.jetbrains.settingsRepository.conflictResolver
|
||||
import org.jetbrains.settingsRepository.copyLocalConfig
|
||||
import org.jetbrains.settingsRepository.git.GitRepositoryManager
|
||||
import org.jetbrains.settingsRepository.git.commit
|
||||
import org.jetbrains.settingsRepository.git.computeIndexDiff
|
||||
@@ -39,16 +42,17 @@ import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.Arrays
|
||||
import java.nio.file.FileSystem
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
// kotlin bug, cannot be val (.NoSuchMethodError: org.jetbrains.settingsRepository.SettingsRepositoryPackage.getMARKER_ACCEPT_MY()[B)
|
||||
object AM {
|
||||
internal object AM {
|
||||
val MARKER_ACCEPT_MY: ByteArray = "__accept my__".toByteArray()
|
||||
val MARKER_ACCEPT_THEIRS: ByteArray = "__accept theirs__".toByteArray()
|
||||
}
|
||||
|
||||
class GitTest : IcsTestCase() {
|
||||
internal class GitTest : IcsTestCase() {
|
||||
companion object {
|
||||
@ClassRule val projectRule = ProjectRule()
|
||||
}
|
||||
@@ -175,7 +179,7 @@ class GitTest : IcsTestCase() {
|
||||
repositoryManager.commit()
|
||||
repositoryManager.pull()
|
||||
assertThat(FileUtil.loadFile(File(repository.getWorkTree(), file.name))).isEqualTo(String(file.data, CharsetToolkit.UTF8_CHARSET))
|
||||
compareFiles(repository.workTree, remoteRepository.workTree, null, PathUtilRt.getFileName(file.name))
|
||||
compareFiles(repository.workTree, remoteRepository.workTree, PathUtilRt.getFileName(file.name))
|
||||
}
|
||||
|
||||
private fun createLocalRepository(remoteBranchName: String? = null) {
|
||||
@@ -188,15 +192,20 @@ class GitTest : IcsTestCase() {
|
||||
return addAndCommit("local.xml")
|
||||
}
|
||||
|
||||
private fun MockVirtualFileSystem.compare() {
|
||||
compareFiles(repository.workTree, remoteRepository.workTree, root)
|
||||
private fun FileSystem.compare(): FileSystem {
|
||||
val root = getPath("/")!!
|
||||
compareFiles(root, repository.workTree)
|
||||
compareFiles(root, remoteRepository.workTree)
|
||||
return this
|
||||
}
|
||||
|
||||
// never was merged. we reset using "merge with strategy "theirs", so, we must test - what's happen if it is not first merge? - see next test
|
||||
@Test fun resetToTheirsIfFirstMerge() {
|
||||
createLocalRepositoryAndCommit(null)
|
||||
sync(SyncType.OVERWRITE_LOCAL)
|
||||
fs().file(SAMPLE_FILE_NAME, SAMPLE_FILE_CONTENT).compare()
|
||||
fs
|
||||
.file(SAMPLE_FILE_NAME, SAMPLE_FILE_CONTENT)
|
||||
.compare()
|
||||
}
|
||||
|
||||
@Test fun resetToTheirsISecondMergeIsNull() {
|
||||
@@ -205,8 +214,6 @@ class GitTest : IcsTestCase() {
|
||||
|
||||
restoreRemoteAfterPush()
|
||||
|
||||
val fs = MockVirtualFileSystem()
|
||||
|
||||
fun testRemote() {
|
||||
fs
|
||||
.file("local.xml", """<file path="local.xml" />""")
|
||||
@@ -232,7 +239,7 @@ class GitTest : IcsTestCase() {
|
||||
createLocalRepositoryAndCommit()
|
||||
sync(SyncType.OVERWRITE_REMOTE)
|
||||
restoreRemoteAfterPush()
|
||||
fs().file("local.xml", """<file path="local.xml" />""").compare()
|
||||
fs.file("local.xml", """<file path="local.xml" />""").compare()
|
||||
}
|
||||
|
||||
@Test fun `reset to my, second merge is null`() {
|
||||
@@ -241,8 +248,10 @@ class GitTest : IcsTestCase() {
|
||||
|
||||
restoreRemoteAfterPush()
|
||||
|
||||
val fs = fs().file("local.xml", """<file path="local.xml" />""").file(SAMPLE_FILE_NAME, SAMPLE_FILE_CONTENT)
|
||||
fs.compare()
|
||||
val fs = fs
|
||||
.file("local.xml", """<file path="local.xml" />""")
|
||||
.file(SAMPLE_FILE_NAME, SAMPLE_FILE_CONTENT)
|
||||
.compare()
|
||||
|
||||
val localToFilePath = "_mac/local2.xml"
|
||||
addAndCommit(localToFilePath)
|
||||
@@ -269,7 +278,7 @@ class GitTest : IcsTestCase() {
|
||||
sync(SyncType.MERGE)
|
||||
|
||||
restoreRemoteAfterPush()
|
||||
fs().file(SAMPLE_FILE_NAME, data.toString(StandardCharsets.UTF_8)).compare()
|
||||
fs.file(SAMPLE_FILE_NAME, data.toString(StandardCharsets.UTF_8)).compare()
|
||||
}
|
||||
|
||||
@Test fun `merge - theirs file deleted, my modified, accept theirs`() {
|
||||
@@ -286,7 +295,7 @@ class GitTest : IcsTestCase() {
|
||||
|
||||
sync(SyncType.MERGE)
|
||||
|
||||
fs().compare()
|
||||
fs.compare()
|
||||
}
|
||||
|
||||
@Test fun `merge - my file deleted, theirs modified, accept my`() {
|
||||
@@ -294,16 +303,16 @@ class GitTest : IcsTestCase() {
|
||||
|
||||
sync(SyncType.MERGE)
|
||||
|
||||
provider.delete("remote.xml")
|
||||
provider.delete(SAMPLE_FILE_NAME)
|
||||
repositoryManager.commit()
|
||||
|
||||
remoteRepository.writePath("remote.xml", AM.MARKER_ACCEPT_THEIRS)
|
||||
remoteRepository.writePath(SAMPLE_FILE_NAME, AM.MARKER_ACCEPT_THEIRS)
|
||||
remoteRepository.commit("")
|
||||
|
||||
sync(SyncType.MERGE)
|
||||
restoreRemoteAfterPush()
|
||||
|
||||
fs().compare()
|
||||
fs.compare()
|
||||
}
|
||||
|
||||
@Test fun `commit if unmerged`() {
|
||||
@@ -327,7 +336,7 @@ class GitTest : IcsTestCase() {
|
||||
}
|
||||
sync(SyncType.MERGE)
|
||||
|
||||
fs().file(SAMPLE_FILE_NAME, SAMPLE_FILE_CONTENT).compare()
|
||||
fs.file(SAMPLE_FILE_NAME, SAMPLE_FILE_CONTENT).compare()
|
||||
}
|
||||
|
||||
// remote is uninitialized (empty - initial commit is not done)
|
||||
@@ -368,6 +377,51 @@ class GitTest : IcsTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun `initial copy to repository: no local files`() {
|
||||
// check error during findRemoteRefUpdatesFor (no master ref)
|
||||
testInitialCopy(false)
|
||||
}
|
||||
|
||||
@Test fun `initial copy to repository: some local files`() {
|
||||
// check error during findRemoteRefUpdatesFor (no master ref)
|
||||
testInitialCopy(true)
|
||||
}
|
||||
|
||||
private fun testInitialCopy(addLocalFiles: Boolean) {
|
||||
createRemoteRepository(initialCommit = false)
|
||||
|
||||
repositoryManager.createRepositoryIfNeed()
|
||||
repositoryManager.setUpstream(remoteRepository.getWorkTree().absolutePath)
|
||||
|
||||
val store = ApplicationStoreImpl(ApplicationManager.getApplication()!!)
|
||||
val localConfigPath = tempDirManager.newPath("local_config")
|
||||
|
||||
val lafData = """<application>
|
||||
<component name="UISettings">
|
||||
<option name="HIDE_TOOL_STRIPES" value="false" />
|
||||
</component>
|
||||
</application>"""
|
||||
if (addLocalFiles) {
|
||||
localConfigPath.writeChild("options/ui.lnf.xml", lafData)
|
||||
}
|
||||
|
||||
store.setPath(localConfigPath.toString())
|
||||
store.storageManager.streamProvider = provider
|
||||
|
||||
icsManager.sync(SyncType.MERGE, projectRule.project, { copyLocalConfig(store.storageManager) })
|
||||
|
||||
if (addLocalFiles) {
|
||||
assertThat(localConfigPath).isDirectory()
|
||||
fs
|
||||
.file("ui.lnf.xml", lafData)
|
||||
restoreRemoteAfterPush()
|
||||
}
|
||||
else {
|
||||
assertThat(localConfigPath).doesNotExist()
|
||||
}
|
||||
fs.compare()
|
||||
}
|
||||
|
||||
private fun createRemoteRepository(branchName: String? = null, initialCommit: Boolean = true) {
|
||||
val repository = tempDirManager.createRepository("upstream")
|
||||
if (initialCommit) {
|
||||
@@ -396,7 +450,6 @@ class GitTest : IcsTestCase() {
|
||||
|
||||
sync(syncType)
|
||||
|
||||
val fs = MockVirtualFileSystem()
|
||||
if (syncType != SyncType.OVERWRITE_LOCAL) {
|
||||
fs.file(path, data)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import org.jetbrains.jgit.dirCache.edit
|
||||
import org.jetbrains.settingsRepository.IcsManager
|
||||
import org.jetbrains.settingsRepository.git
|
||||
import org.junit.Rule
|
||||
import java.nio.file.FileSystem
|
||||
import java.nio.file.Path
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
fun Repository.add(path: String, data: String) = add(path, data.toByteArray())
|
||||
|
||||
@@ -46,6 +46,12 @@ abstract class IcsTestCase {
|
||||
val tempDirManager = TemporaryDirectory()
|
||||
@Rule fun getTemporaryFolder() = tempDirManager
|
||||
|
||||
private val fsRule = InMemoryFsRule()
|
||||
@Rule fun _inMemoryFsRule() = fsRule
|
||||
|
||||
val fs: FileSystem
|
||||
get() = fsRule.fs
|
||||
|
||||
val icsManager by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val icsManager = IcsManager(tempDirManager.newDirectory())
|
||||
icsManager.repositoryManager.createRepositoryIfNeed()
|
||||
|
||||
@@ -15,31 +15,58 @@
|
||||
*/
|
||||
package org.jetbrains.settingsRepository.test
|
||||
|
||||
import com.intellij.mock.MockVirtualFileSystem
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder
|
||||
import com.intellij.testFramework.isFile
|
||||
import gnu.trove.THashSet
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.eclipse.jgit.lib.Constants
|
||||
import org.junit.rules.ExternalResource
|
||||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
import java.net.URLEncoder
|
||||
import java.nio.file.FileSystem
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
data class FileInfo(val name: String, val data: ByteArray)
|
||||
|
||||
fun fs() = MockVirtualFileSystem()
|
||||
class InMemoryFsRule : ExternalResource() {
|
||||
private var _fs: FileSystem? = null
|
||||
|
||||
private var sanitizedName: String by Delegates.notNull()
|
||||
|
||||
override fun apply(base: Statement, description: Description): Statement {
|
||||
sanitizedName = URLEncoder.encode(description.methodName, Charsets.UTF_8.name())
|
||||
return super.apply(base, description)
|
||||
}
|
||||
|
||||
val fs: FileSystem
|
||||
get() {
|
||||
var r = _fs
|
||||
if (r == null) {
|
||||
r = MemoryFileSystemBuilder
|
||||
.newLinux()
|
||||
.setCurrentWorkingDirectory("/")
|
||||
.build(sanitizedName)
|
||||
_fs = r
|
||||
}
|
||||
return r!!
|
||||
}
|
||||
|
||||
override fun after() {
|
||||
_fs?.close()
|
||||
_fs = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getChildrenStream(path: Path, excludes: Array<out String>? = null) = Files.list(path)
|
||||
.filter { !it.endsWith(Constants.DOT_GIT) && (excludes == null || !excludes.contains(it.fileName.toString())) }
|
||||
.sorted()
|
||||
|
||||
internal fun compareFiles(path1: Path, path2: Path, path3: VirtualFile? = null, vararg localExcludes: String) {
|
||||
fun compareFiles(path1: Path, path2: Path, vararg localExcludes: String) {
|
||||
assertThat(path1).isDirectory()
|
||||
assertThat(path2).isDirectory()
|
||||
if (path3 != null) {
|
||||
assertThat(path3.isDirectory).isTrue()
|
||||
}
|
||||
|
||||
val notFound = THashSet<Path>()
|
||||
for (path in getChildrenStream(path1, localExcludes)) {
|
||||
@@ -47,21 +74,15 @@ internal fun compareFiles(path1: Path, path2: Path, path3: VirtualFile? = null,
|
||||
}
|
||||
|
||||
for (child2 in getChildrenStream(path2)) {
|
||||
val fileName = child2.fileName
|
||||
val child1 = path1.resolve(fileName)
|
||||
val child3 = path3?.findChild(fileName.toString())
|
||||
val child1 = path1.resolve(child2.fileName.toString())
|
||||
if (child1.isFile()) {
|
||||
assertThat(child2).hasSameContentAs(child1)
|
||||
if (child3 != null) {
|
||||
assertThat(child3.isDirectory).isFalse()
|
||||
assertThat(child1).hasContent(if (child3 is LightVirtualFile) child3.content.toString() else VfsUtilCore.loadText(child3))
|
||||
}
|
||||
}
|
||||
else {
|
||||
compareFiles(child1, child2, child3, *localExcludes)
|
||||
compareFiles(child1, child2, *localExcludes)
|
||||
}
|
||||
notFound.remove(child1)
|
||||
}
|
||||
|
||||
assertThat(notFound).isEmpty()
|
||||
assertThat(notFound).`as`("Path '$path1' contains other files than '$path2'").isEmpty()
|
||||
}
|
||||
Reference in New Issue
Block a user