use nio Path

This commit is contained in:
Vladimir Krivosheev
2016-02-11 19:18:26 +01:00
parent dd9a7b9d7a
commit 2dcea49d91
32 changed files with 333 additions and 303 deletions
@@ -35,7 +35,7 @@ private class BuiltInWebServerTest : BuiltInServerTestCase() {
private fun testIndex(vararg paths: String) {
val project = BuiltInServerTestCase.projectRule.project
val newPath = tempDirManager.newPath(refreshVfs = false)
val newPath = tempDirManager.newPath()
newPath.writeChild(manager.filePath!!, "hello")
newPath.refreshVfs()
@@ -49,7 +49,7 @@ internal class TestManager(val projectRule: ProjectRule, private val tempDirMana
projectRule.project
if (filePath!! == "_tmp_") {
val file = tempDirManager.newPath(".txt")
val file = tempDirManager.newPath(".txt", refreshVfs = true)
if (!annotation!!.doNotCreate) {
file.createFile()
}
@@ -33,14 +33,15 @@ import com.intellij.util.LineSeparator
import com.intellij.util.SmartList
import com.intellij.util.SystemProperties
import com.intellij.util.containers.SmartHashSet
import com.intellij.util.systemIndependentPath
import gnu.trove.THashMap
import org.jdom.Element
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.file.Path
open class DirectoryBasedStorage(private val dir: File,
open class DirectoryBasedStorage(private val dir: Path,
private val splitter: StateSplitter,
private val pathMacroSubstitutor: TrackingPathMacroSubstitutor? = null) : StateStorageBase<StateMap>() {
private @Volatile var virtualFile: VirtualFile? = null
@@ -93,7 +94,7 @@ open class DirectoryBasedStorage(private val dir: File,
private fun getVirtualFile(): VirtualFile? {
var result = virtualFile
if (result == null) {
result = LocalFileSystem.getInstance().findFileByIoFile(dir)
result = LocalFileSystem.getInstance().findFileByPath(dir.systemIndependentPath)
virtualFile = result
}
return result
@@ -27,7 +27,8 @@ import com.intellij.openapi.project.Project
import com.intellij.util.SmartList
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.lang.CompoundRuntimeException
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
const val ROOT_CONFIG = "\$ROOT_CONFIG$"
@@ -59,7 +60,7 @@ sealed class SchemeManagerFactoryBase : SchemesManagerFactory(), SettingsSavingC
return originalPath
}
abstract fun pathToFile(path: String, storageManager: StateStorageManager): File
abstract fun pathToFile(path: String, storageManager: StateStorageManager): Path
fun process(processor: (SchemeManagerImpl<Scheme, ExternalizableScheme>) -> Unit) {
for (manager in managers) {
@@ -100,12 +101,12 @@ sealed class SchemeManagerFactoryBase : SchemesManagerFactory(), SettingsSavingC
return path
}
override fun pathToFile(path: String, storageManager: StateStorageManager) = File(storageManager.expandMacros("$ROOT_CONFIG/$path"))
override fun pathToFile(path: String, storageManager: StateStorageManager) = Paths.get(storageManager.expandMacros(ROOT_CONFIG), path)
}
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) = Paths.get(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
}
}
@@ -35,28 +35,24 @@ import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.newvfs.NewVirtualFile
import com.intellij.openapi.vfs.tracker.VirtualFileTracker
import com.intellij.util.PathUtil
import com.intellij.util.PathUtilRt
import com.intellij.util.SmartList
import com.intellij.util.ThrowableConvertor
import com.intellij.util.*
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.io.URLUtil
import com.intellij.util.text.UniqueNameGenerator
import gnu.trove.THashMap
import gnu.trove.THashSet
import gnu.trove.TObjectObjectProcedure
import gnu.trove.TObjectProcedure
import org.jdom.Document
import org.jdom.Element
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.nio.file.Path
import java.util.*
class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: String,
private val processor: SchemeProcessor<E>,
private val provider: StreamProvider?,
private val ioDirectory: File,
private val ioDirectory: Path,
val roamingType: RoamingType = RoamingType.DEFAULT,
virtualFileTrackerDisposable: Disposable? = null,
val presentableName: String? = null) : SchemesManager<T, E>(), SafeWriteRequestor {
@@ -104,7 +100,7 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
private fun refreshVirtualDirectoryAndAddListener(virtualFileTrackerDisposable: Disposable?) {
// store refreshes root directory, so, we don't need to use refreshAndFindFile
val directory = LocalFileSystem.getInstance().findFileByIoFile(ioDirectory) ?: return
val directory = LocalFileSystem.getInstance().findFileByPath(ioDirectory.systemIndependentPath) ?: return
this.directory = directory
directory.children
@@ -118,7 +114,7 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
}
private fun addVfsListener(virtualFileTrackerDisposable: Disposable?) {
service<VirtualFileTracker>().addTracker("${LocalFileSystem.PROTOCOL_PREFIX}${ioDirectory.absolutePath.replace(File.separatorChar, '/')}", object : VirtualFileAdapter() {
service<VirtualFileTracker>().addTracker("${LocalFileSystem.PROTOCOL_PREFIX}${ioDirectory.toAbsolutePath().systemIndependentPath}", object : VirtualFileAdapter() {
override fun contentsChanged(event: VirtualFileEvent) {
if (event.requestor != null || !isMy(event)) {
return
@@ -268,17 +264,17 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
}
}
else {
ioDirectory.listFiles({ parent, name -> canRead(name) })?.let {
ioDirectory.directoryStreamIfExists({ canRead(it.fileName.toString()) }) {
for (file in it) {
if (file.isDirectory) {
if (file.isDirectory()) {
continue
}
try {
loadScheme(file.name, file.inputStream(), true)
loadScheme(file.fileName.toString(), file.inputStream(), true)
}
catch (e: Throwable) {
LOG.error("Cannot read scheme ${file.path}", e)
LOG.error("Cannot read scheme $file", e)
}
}
}
@@ -467,16 +463,16 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
}
private fun removeDirectoryIfEmpty(errors: MutableList<Throwable>) {
ioDirectory.listFiles()?.let {
ioDirectory.directoryStreamIfExists {
for (file in it) {
if (!file.isHidden) {
LOG.info("Directory ${ioDirectory.name} is not deleted: at least one file ${file.name} exists")
return
if (!file.isHidden()) {
LOG.info("Directory ${ioDirectory.fileName} is not deleted: at least one file ${file.fileName} exists")
return@removeDirectoryIfEmpty
}
}
}
LOG.info("Remove schemes directory ${ioDirectory.name}")
LOG.info("Remove schemes directory ${ioDirectory.fileName}")
directory = null
var deleteUsingIo = !useVfs
@@ -496,7 +492,7 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
}
if (deleteUsingIo) {
errors.catch { FileUtil.delete(ioDirectory) }
errors.catch { ioDirectory.deleteRecursively() }
}
}
@@ -581,7 +577,7 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
if (renamed) {
externalInfo!!.scheduleDelete()
}
FileUtil.writeToFile(File(ioDirectory, fileName), byteOut.internalBuffer, 0, byteOut.size())
ioDirectory.resolve(fileName).write(byteOut.internalBuffer, 0, byteOut.size())
}
}
else {
@@ -655,7 +651,7 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
if (deleteUsingIo) {
for (name in filesToDelete) {
errors.catch { FileUtil.delete(File(ioDirectory, name)) }
errors.catch { ioDirectory.resolve(name).delete() }
}
}
@@ -665,13 +661,13 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
private fun getDirectory(): VirtualFile? {
var result = directory
if (result == null) {
result = LocalFileSystem.getInstance().findFileByIoFile(ioDirectory)
result = LocalFileSystem.getInstance().findFileByPath(ioDirectory.systemIndependentPath)
directory = result
}
return result
}
override fun getRootDirectory() = ioDirectory
override fun getRootDirectory() = ioDirectory.toFile()
override fun setSchemes(newSchemes: List<T>, newCurrentScheme: T?, removeCondition: Condition<T>?) {
val oldCurrentScheme = currentScheme
@@ -705,25 +701,23 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
return
}
schemeToInfo.retainEntries(object : TObjectObjectProcedure<E, ExternalInfo> {
override fun execute(scheme: E, info: ExternalInfo): Boolean {
if (readOnlyExternalizableSchemes[scheme.name] == scheme) {
return true
}
for (t in newSchemes) {
// by identity
if (t === scheme) {
if (filesToDelete.isNotEmpty()) {
filesToDelete.remove("${info.fileName}")
}
return true
}
}
info.scheduleDelete()
return false
schemeToInfo.retainEntries(TObjectObjectProcedure<E, ExternalInfo> { scheme, info ->
if (readOnlyExternalizableSchemes[scheme.name] == scheme) {
return@TObjectObjectProcedure true
}
for (t in newSchemes) {
// by identity
if (t === scheme) {
if (filesToDelete.isNotEmpty()) {
filesToDelete.remove("${info.fileName}")
}
return@TObjectObjectProcedure true
}
}
info.scheduleDelete()
false
})
}
@@ -777,12 +771,10 @@ class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(val fileSpec: Stri
}
override fun clearAllSchemes() {
schemeToInfo.forEachValue(object : TObjectProcedure<ExternalInfo> {
override fun execute(info: ExternalInfo): Boolean {
info.scheduleDelete()
return true
}
})
schemeToInfo.forEachValue {
it.scheduleDelete()
true
}
currentScheme = null
schemes.clear()
@@ -895,11 +887,11 @@ private inline fun MutableList<Throwable>.catch(runnable: () -> Unit) {
}
}
fun createDir(ioDir: File, requestor: Any): VirtualFile {
ioDir.mkdirs()
fun createDir(ioDir: Path, requestor: Any): VirtualFile {
ioDir.createDirectories()
val parentFile = ioDir.parent
val parentVirtualFile = (if (parentFile == null) null else VfsUtil.createDirectoryIfMissing(parentFile)) ?: throw IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile))
return getFile(ioDir.name, parentVirtualFile, requestor)
val parentVirtualFile = (if (parentFile == null) null else VfsUtil.createDirectoryIfMissing(parentFile.systemIndependentPath)) ?: throw IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile))
return getFile(ioDir.fileName.toString(), parentVirtualFile, requestor)
}
fun getFile(fileName: String, parent: VirtualFile, requestor: Any): VirtualFile {
@@ -36,6 +36,8 @@ import org.jdom.Element
import org.jetbrains.annotations.TestOnly
import java.io.File
import java.io.IOException
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.concurrent.locks.ReentrantLock
import java.util.regex.Pattern
@@ -195,7 +197,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
val filePath = expandMacros(collapsedPath)
@Suppress("DEPRECATION")
if (stateSplitter != StateSplitter::class.java && stateSplitter != StateSplitterEx::class.java) {
val storage = MyDirectoryStorage(this, File(filePath), ReflectionUtil.newInstance(stateSplitter))
val storage = MyDirectoryStorage(this, Paths.get(filePath), ReflectionUtil.newInstance(stateSplitter))
virtualFileTracker?.put(filePath, storage)
return storage
}
@@ -212,7 +214,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
return storage
}
private class MyDirectoryStorage(override val storageManager: StateStorageManagerImpl, file: File, @Suppress("DEPRECATION") splitter: StateSplitter) :
private class MyDirectoryStorage(override val storageManager: StateStorageManagerImpl, file: Path, @Suppress("DEPRECATION") splitter: StateSplitter) :
DirectoryBasedStorage(file, splitter, storageManager.pathMacroSubstitutor), StorageVirtualFileTracker.TrackedStorage
private class MyFileStorage(override val storageManager: StateStorageManagerImpl,
@@ -62,7 +62,7 @@ internal class ApplicationStoreTest {
private var componentStore: MyComponentStore by Delegates.notNull()
@Before fun setUp() {
testAppConfig = tempDirManager.newPath(refreshVfs = false)
testAppConfig = tempDirManager.newPath()
componentStore = MyComponentStore(testAppConfig.systemIndependentPath)
}
@@ -220,7 +220,7 @@ internal class ApplicationStoreTest {
@Test fun `don't save if only format is changed`() {
val oldContent = "<application><component name=\"A\" foo=\"old\" deprecated=\"old\"/></application>"
val file = writeConfig("a.xml", oldContent)
val oldModificationTime = file.getLastModifiedTime()
val oldModificationTime = file.lastModified()
testAppConfig.refreshVfs()
val component = A()
@@ -230,7 +230,7 @@ internal class ApplicationStoreTest {
saveStore()
assertThat(file).hasContent(oldContent)
assertThat(oldModificationTime).isEqualTo(file.getLastModifiedTime())
assertThat(oldModificationTime).isEqualTo(file.lastModified())
component.options.bar = "2"
component.options.foo = "1"
@@ -65,8 +65,8 @@ internal class DirectoryBasedStorageTest {
@Rule fun getChain() = ruleChain
@Test fun save() {
val dir = tempDirManager.newPath()
val storage = DirectoryBasedStorage(dir.toFile(), TestStateSplitter())
val dir = tempDirManager.newPath(refreshVfs = true)
val storage = DirectoryBasedStorage(dir, TestStateSplitter())
val componentName = "test"
@@ -47,7 +47,7 @@ internal class ModuleStoreRenameTest {
object : ExternalResource() {
override fun before() {
runInEdtAndWait {
module = projectRule.createModule(tempDirManager.newPath().resolve("m.iml"))
module = projectRule.createModule(tempDirManager.newPath(refreshVfs = true).resolve("m.iml"))
}
module.messageBus.connect().subscribe(ProjectTopics.MODULES, object : ModuleAdapter() {
@@ -76,7 +76,7 @@ class ModuleStoreTest {
@Test fun `must be empty if classpath storage`() {
// we must not use VFS here, file must not be created
val moduleFile = tempDirManager.newPath("module").resolve("test.iml")
val moduleFile = tempDirManager.newPath("module", refreshVfs = true).resolve("test.iml")
moduleFile.createModule().useAndDispose {
ModuleRootModificationUtil.addContentRoot(this, moduleFile.parentSystemIndependentPath)
saveStore()
@@ -92,7 +92,7 @@ class ModuleStoreTest {
@Test fun `one batch update session if several modules changed`() {
val nameToCount = TObjectIntHashMap<String>()
val root = tempDirManager.newPath()
val root = tempDirManager.newPath(refreshVfs = true)
fun Module.addContentRoot() {
val moduleName = name
@@ -27,11 +27,11 @@ import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.project.impl.ProjectImpl
import com.intellij.openapi.project.impl.ProjectManagerImpl
import com.intellij.openapi.util.io.systemIndependentPath
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.*
import com.intellij.util.PathUtil
import com.intellij.util.readText
import com.intellij.util.systemIndependentPath
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.ClassRule
@@ -52,7 +52,7 @@ private fun createOrLoadProject(tempDirManager: TemporaryDirectory, task: (Proje
runInEdtAndWait {
var filePath: String
if (projectCreator == null) {
filePath = tempDirManager.newDirectory("test${if (directoryBased) "" else ProjectFileType.DOT_DEFAULT_EXTENSION}").systemIndependentPath
filePath = tempDirManager.newPath("test${if (directoryBased) "" else ProjectFileType.DOT_DEFAULT_EXTENSION}").systemIndependentPath
}
else {
filePath = runWriteAction { projectCreator(tempDirManager.newVirtualDirectory()) }
@@ -18,13 +18,12 @@ package com.intellij.configurationStore
import com.intellij.openapi.options.BaseSchemeProcessor
import com.intellij.openapi.options.ExternalizableScheme
import com.intellij.openapi.options.SchemesManagerFactory
import com.intellij.openapi.util.JDOMUtil
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.ProjectRule
import com.intellij.testFramework.TemporaryDirectory
import com.intellij.util.SmartList
import com.intellij.util.*
import com.intellij.util.lang.CompoundRuntimeException
import com.intellij.util.xmlb.XmlSerializer
import com.intellij.util.xmlb.annotations.Attribute
@@ -40,6 +39,7 @@ import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import java.io.File
import java.nio.file.Path
internal val FILE_SPEC = "REMOTE"
@@ -55,8 +55,8 @@ internal class SchemeManagerTest {
private val tempDirManager = TemporaryDirectory()
@Rule fun getTemporaryFolder() = tempDirManager
private var localBaseDir: File? = null
private var remoteBaseDir: File? = null
private var localBaseDir: Path? = null
private var remoteBaseDir: Path? = null
private fun getTestDataPath() = PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/platform/platform-tests/testData/options"
@@ -112,14 +112,14 @@ internal class SchemeManagerTest {
firstScheme!!.name = "first_renamed"
manager.save()
checkSchemes(File(remoteBaseDir, "REMOTE"), "first_renamed->first_renamed;2->second", true)
checkSchemes(remoteBaseDir!!.resolve("REMOTE"), "first_renamed->first_renamed;2->second", true)
checkSchemes(localBaseDir!!, "", false)
firstScheme.name = "first_renamed2"
manager.removeScheme(firstScheme)
manager.save()
checkSchemes(File(remoteBaseDir, "REMOTE"), "2->second", true)
checkSchemes(remoteBaseDir!!.resolve("REMOTE"), "2->second", true)
checkSchemes(localBaseDir!!, "", false)
}
@@ -142,16 +142,16 @@ internal class SchemeManagerTest {
assertThat("first2").isEqualTo(scheme.name)
}
fun TestScheme.save(file: File) {
FileUtil.writeToFile(file, serialize().toByteArray())
fun TestScheme.save(file: Path) {
file.write(serialize().toByteArray())
}
@Test fun `different extensions`() {
val dir = tempDirManager.newDirectory()
val dir = tempDirManager.newPath()
val scheme = TestScheme("local", "true")
scheme.save(File(dir, "1.icls"))
TestScheme("local", "false").save(File(dir, "1.xml"))
scheme.save(dir.resolve("1.icls"))
TestScheme("local", "false").save(dir.resolve("1.xml"))
val schemesManager = SchemeManagerImpl<TestScheme, TestScheme>(FILE_SPEC, object: TestSchemesProcessor() {
override fun isUpgradeNeeded() = true
@@ -161,18 +161,18 @@ internal class SchemeManagerTest {
schemesManager.loadSchemes()
assertThat(schemesManager.allSchemes).containsOnly(scheme)
assertThat(File(dir, "1.icls")).isFile()
assertThat(File(dir, "1.xml")).isFile()
assertThat(dir.resolve("1.icls")).isRegularFile()
assertThat(dir.resolve("1.xml")).isRegularFile()
scheme.data = "newTrue"
schemesManager.save()
assertThat(File(dir, "1.icls")).isFile()
assertThat(File(dir, "1.xml")).doesNotExist()
assertThat(dir.resolve("1.icls")).isRegularFile()
assertThat(dir.resolve("1.xml")).doesNotExist()
}
@Test fun setSchemes() {
val dir = tempDirManager.newDirectory()
val dir = tempDirManager.newPath()
val schemeManager = createSchemeManager(dir)
schemeManager.loadSchemes()
assertThat(schemeManager.allSchemes).isEmpty()
@@ -183,12 +183,12 @@ internal class SchemeManagerTest {
val schemes = schemeManager.allSchemes
assertThat(schemes).containsOnly(scheme)
assertThat(File(dir, "s1.xml")).doesNotExist()
assertThat(dir.resolve("s1.xml")).doesNotExist()
scheme.data = "newTrue"
schemeManager.save()
assertThat(File(dir, "s1.xml")).isFile()
assertThat(dir.resolve("s1.xml")).isRegularFile()
schemeManager.setSchemes(emptyList())
@@ -198,7 +198,7 @@ internal class SchemeManagerTest {
}
@Test fun `save only if scheme differs from bundled`() {
val dir = tempDirManager.newDirectory()
val dir = tempDirManager.newPath()
var schemeManager = createSchemeManager(dir)
val converter: (Element) -> TestScheme = { XmlSerializer.deserialize(it, TestScheme::class.java)!! }
val bundledPath = "/bundledSchemes/default"
@@ -219,7 +219,7 @@ internal class SchemeManagerTest {
customScheme.data = "foo"
schemeManager.save()
assertThat(File(dir, "default.xml")).isFile()
assertThat(dir.resolve("default.xml")).isRegularFile()
schemeManager = createSchemeManager(dir)
schemeManager.loadBundledScheme(bundledPath, this, converter)
@@ -230,7 +230,7 @@ internal class SchemeManagerTest {
}
@Test fun `don't remove dir if no schemes but at least one non-hidden file exists`() {
val dir = tempDirManager.newDirectory()
val dir = tempDirManager.newPath()
val schemeManager = createSchemeManager(dir)
val scheme = TestScheme("s1")
@@ -238,12 +238,12 @@ internal class SchemeManagerTest {
schemeManager.save()
val schemeFile = File(dir, "s1.xml")
assertThat(schemeFile).isFile()
val schemeFile = dir.resolve("s1.xml")
assertThat(schemeFile).isRegularFile()
schemeManager.setSchemes(emptyList())
FileUtil.writeToFile(File(dir, "empty"), byteArrayOf())
dir.resolve("empty").write(byteArrayOf())
schemeManager.save()
@@ -252,11 +252,11 @@ internal class SchemeManagerTest {
}
@Test fun `remove empty directory only if some file was deleted`() {
val dir = tempDirManager.newDirectory()
val dir = tempDirManager.newPath()
val schemeManager = createSchemeManager(dir)
schemeManager.loadSchemes()
assertThat(dir.mkdirs()).isTrue()
dir.createDirectories()
schemeManager.save()
assertThat(dir).isDirectory()
@@ -270,7 +270,7 @@ internal class SchemeManagerTest {
}
@Test fun rename() {
val dir = tempDirManager.newDirectory()
val dir = tempDirManager.newPath()
val schemeManager = createSchemeManager(dir)
schemeManager.loadSchemes()
assertThat(schemeManager.allSchemes).isEmpty()
@@ -281,19 +281,19 @@ internal class SchemeManagerTest {
val schemes = schemeManager.allSchemes
assertThat(schemes).containsOnly(scheme)
assertThat(File(dir, "s1.xml")).doesNotExist()
assertThat(dir.resolve("s1.xml")).doesNotExist()
scheme.data = "newTrue"
schemeManager.save()
assertThat(File(dir, "s1.xml")).isFile()
assertThat(dir.resolve("s1.xml")).isRegularFile()
scheme.name = "s2"
schemeManager.save()
assertThat(File(dir, "s1.xml")).doesNotExist()
assertThat(File(dir, "s2.xml")).isFile()
assertThat(dir.resolve("s1.xml")).doesNotExist()
assertThat(dir.resolve("s2.xml")).isRegularFile()
}
@Test fun `path must not contains ROOT_CONFIG macro`() {
@@ -304,7 +304,7 @@ internal class SchemeManagerTest {
assertThatThrownBy({SchemesManagerFactory.getInstance().create<TestScheme, TestScheme>("foo\\bar", TestSchemesProcessor())}).hasMessage("Path must be system-independent, use forward slash instead of backslash")
}
private fun createSchemeManager(dir: File) = SchemeManagerImpl<TestScheme, TestScheme>(FILE_SPEC, TestSchemesProcessor(), null, dir)
private fun createSchemeManager(dir: Path) = SchemeManagerImpl<TestScheme, TestScheme>(FILE_SPEC, TestSchemesProcessor(), null, dir)
private fun createAndLoad(testData: String): SchemeManagerImpl<TestScheme, TestScheme> {
createTempFiles(testData)
@@ -314,30 +314,30 @@ internal class SchemeManagerTest {
private fun doLoadSaveTest(testData: String, expected: String, localExpected: String = "") {
val schemesManager = createAndLoad(testData)
schemesManager.save()
checkSchemes(File(remoteBaseDir, "REMOTE"), expected, true)
checkSchemes(remoteBaseDir!!.resolve("REMOTE"), expected, true)
checkSchemes(localBaseDir!!, localExpected, false)
}
private fun checkSchemes(expected: String) {
checkSchemes(File(remoteBaseDir, "REMOTE"), expected, true)
checkSchemes(remoteBaseDir!!.resolve("REMOTE"), expected, true)
checkSchemes(localBaseDir!!, "", false)
}
private fun createAndLoad(): SchemeManagerImpl<TestScheme, TestScheme> {
val schemesManager = SchemeManagerImpl<TestScheme, TestScheme>(FILE_SPEC, TestSchemesProcessor(), MockStreamProvider(remoteBaseDir!!), localBaseDir!!)
val schemesManager = SchemeManagerImpl<TestScheme, TestScheme>(FILE_SPEC, TestSchemesProcessor(), MockStreamProvider(remoteBaseDir!!.toFile()), localBaseDir!!)
schemesManager.loadSchemes()
return schemesManager
}
private fun createTempFiles(testData: String) {
val temp = tempDirManager.newDirectory()
localBaseDir = File(temp, "__local")
val temp = tempDirManager.newPath()
localBaseDir = temp.resolve("__local")
remoteBaseDir = temp
FileUtil.copyDir(File("${getTestDataPath()}/$testData"), File(temp, "REMOTE"))
FileUtil.copyDir(File("${getTestDataPath()}/$testData"), temp.resolve("REMOTE").toFile())
}
}
private fun checkSchemes(baseDir: File, expected: String, ignoreDeleted: Boolean) {
private fun checkSchemes(baseDir: Path, expected: String, ignoreDeleted: Boolean) {
val filesToScheme = StringUtil.split(expected, ";")
val fileToSchemeMap = THashMap<String, String>()
for (fileToScheme in filesToScheme) {
@@ -345,10 +345,9 @@ private fun checkSchemes(baseDir: File, expected: String, ignoreDeleted: Boolean
fileToSchemeMap.put(fileToScheme.substring(0, index), fileToScheme.substring(index + 2))
}
val files = baseDir.listFiles()
if (files != null) {
for (file in files) {
val fileName = FileUtil.getNameWithoutExtension(file)
baseDir.directoryStreamIfExists {
for (file in it) {
val fileName = FileUtil.getNameWithoutExtension(file.fileName.toString())
if ("--deleted" == fileName && ignoreDeleted) {
assertThat(fileToSchemeMap).containsKey(fileName)
}
@@ -356,14 +355,14 @@ private fun checkSchemes(baseDir: File, expected: String, ignoreDeleted: Boolean
}
for (file in fileToSchemeMap.keys) {
assertThat(File(baseDir, "$file.xml")).isFile()
assertThat(baseDir.resolve("$file.xml")).isRegularFile()
}
if (files != null) {
baseDir.directoryStreamIfExists {
val schemesProcessor = TestSchemesProcessor()
for (file in files) {
val scheme = schemesProcessor.readScheme(JDOMUtil.load(file), true)!!
assertThat(fileToSchemeMap.get(FileUtil.getNameWithoutExtension(file))).isEqualTo(scheme.name)
for (file in it) {
val scheme = schemesProcessor.readScheme(loadElement(file), true)!!
assertThat(fileToSchemeMap.get(FileUtil.getNameWithoutExtension(file.fileName.toString()))).isEqualTo(scheme.name)
}
}
}
@@ -21,12 +21,8 @@ import com.intellij.openapi.vfs.VfsUtil
import java.io.File
import java.io.IOException
import java.io.OutputStream
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.SimpleFileVisitor
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.attribute.FileTime
fun Path.exists() = Files.exists(this)
@@ -74,7 +70,7 @@ fun Path.deleteRecursively(): Path = if (exists()) Files.walkFileTree(this, obje
}
}) else this
fun Path.getLastModifiedTime(): FileTime? = Files.getLastModifiedTime(this)
fun Path.lastModified() = Files.getLastModifiedTime(this)
val Path.systemIndependentPath: String
get() = toString().replace(File.separatorChar, '/')
@@ -90,15 +86,33 @@ fun Path.writeChild(relativePath: String, data: ByteArray) = resolve(relativePat
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.write(data: ByteArray, offset: Int = 0, length: Int = data.size): Path {
outputStream().use { it.write(data, offset, length) }
return this
}
fun Path.size() = Files.size(this)
fun Path.sizeOrNull(): Long {
val attributes: BasicFileAttributes
try {
attributes = Files.readAttributes(this, BasicFileAttributes::class.java)
}
catch (ignored: IOException) {
return -1
}
return attributes.size()
}
fun Path.isHidden() = Files.isHidden(this)
fun Path.isDirectory() = Files.isDirectory(this)
fun Path.isFile() = Files.isRegularFile(this)
fun Path.move(target: Path) = Files.move(this, target)
/**
* Opposite to Java, parent directories will be created
*/
@@ -115,4 +129,22 @@ fun Path.refreshVfs() {
VfsUtil.markDirtyAndRefresh(false, true, true, virtualFile)
}
}
}
inline fun <R> Path.directoryStreamIfExists(task: (stream: DirectoryStream<Path>) -> R): R? {
try {
Files.newDirectoryStream(this).use(task)
}
catch (ignored: NoSuchFileException) {
}
return null
}
inline fun <R> Path.directoryStreamIfExists(noinline filter: ((path: Path) -> Boolean), task: (stream: DirectoryStream<Path>) -> R): R? {
try {
Files.newDirectoryStream(this, { filter.invoke(it) }).use(task)
}
catch (ignored: NoSuchFileException) {
}
return null
}
@@ -37,18 +37,16 @@ class FileSet(private val rootDir: Path) {
}
fun deleteOtherFiles() {
unusedFiles.forEach(object : TObjectProcedure<Path> {
override fun execute(path: Path): Boolean {
if (Files.deleteIfExists(path)) {
val parent = path.parent
Files.newDirectoryStream(parent).use { stream ->
if (!stream.iterator().hasNext()) {
Files.delete(parent)
}
unusedFiles.forEach(TObjectProcedure<Path> { it ->
if (Files.deleteIfExists(it)) {
val parent = it.parent
Files.newDirectoryStream(parent).use { stream ->
if (!stream.iterator().hasNext()) {
Files.delete(parent)
}
}
return true
}
true
})
}
}
@@ -25,7 +25,6 @@ import com.intellij.util.lang.CompoundRuntimeException
import org.junit.rules.ExternalResource
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.io.File
import java.io.IOException
import java.nio.file.Path
import java.nio.file.Paths
@@ -55,12 +54,7 @@ class TemporaryDirectory : ExternalResource() {
paths.clear()
}
/**
* Directory is not created.
*/
fun newDirectory(directoryName: String? = null): File = generatePath(directoryName).toFile()
fun newPath(directoryName: String? = null, refreshVfs: Boolean = true): Path {
fun newPath(directoryName: String? = null, refreshVfs: Boolean = false): Path {
val path = generatePath(directoryName)
if (refreshVfs) {
path.refreshVfs()
@@ -19,62 +19,53 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.invokeAndWaitIfNeed
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.fileTypes.StdFileTypes
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer
import com.intellij.openapi.vcs.merge.MergeProvider2
import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.LightVirtualFile
import com.intellij.util.PathUtilRt
import java.io.File
import java.io.FileInputStream
import com.intellij.util.*
import java.io.InputStream
import java.io.OutputStream
import java.nio.file.Path
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
abstract class BaseRepositoryManager(protected val dir: File) : RepositoryManager {
abstract class BaseRepositoryManager(protected val dir: Path) : RepositoryManager {
protected val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()
override fun processChildren(path: String, filter: (name: String) -> Boolean, processor: (name: String, inputStream: InputStream) -> Boolean) {
var files: Array<out File>? = null
lock.read {
files = File(dir, path).listFiles({ file, name -> filter(name) })
}
if (files == null || files!!.isEmpty()) {
return
}
for (file in files!!) {
if (file.isDirectory || file.isHidden) {
continue;
}
// we ignore empty files as well - delete if corrupted
if (file.length() == 0L) {
if (file.exists()) {
try {
LOG.warn("File $path is empty (length 0), will be removed")
delete(file, path)
}
catch (e: Exception) {
LOG.error(e)
}
dir.resolve(path).directoryStreamIfExists {
for (file in it) {
if (file.isDirectory() || file.isHidden()) {
continue;
}
continue;
}
if (!processor(file.name, file.inputStream())) {
break;
// we ignore empty files as well - delete if corrupted
if (file.size() == 0L) {
if (file.exists()) {
try {
LOG.warn("File $path is empty (length 0), will be removed")
delete(file, path)
}
catch (e: Exception) {
LOG.error(e)
}
}
continue;
}
if (!processor(file.fileName.toString(), file.inputStream())) {
break;
}
}
}
}
override fun deleteRepository() {
FileUtil.delete(dir)
dir.deleteRecursively()
}
protected open fun isPathIgnored(path: String): Boolean = false
@@ -85,21 +76,22 @@ abstract class BaseRepositoryManager(protected val dir: File) : RepositoryManage
return null
}
var fileToDelete: File? = null
var fileToDelete: Path? = null
lock.read {
val file = File(dir, path)
// we ignore empty files as well - delete if corrupted
if (file.length() == 0L) {
fileToDelete = file
}
else {
return FileInputStream(file)
val file = dir.resolve(path)
when (file.sizeOrNull()) {
-1L -> return null
0L -> {
// we ignore empty files as well - delete if corrupted
fileToDelete = file
}
else -> return file.inputStream()
}
}
try {
lock.write {
if (fileToDelete!!.exists() && fileToDelete!!.length() == 0L) {
if (fileToDelete!!.sizeOrNull() == 0L) {
LOG.warn("File $path is empty (length 0), will be removed")
delete(fileToDelete!!, path)
}
@@ -121,9 +113,8 @@ abstract class BaseRepositoryManager(protected val dir: File) : RepositoryManage
try {
lock.write {
val file = File(dir, path)
FileUtil.writeToFile(file, content, 0, size)
val file = dir.resolve(path)
file.write(content, 0, size)
addToIndex(file, path, content, size)
}
}
@@ -137,13 +128,13 @@ abstract class BaseRepositoryManager(protected val dir: File) : RepositoryManage
/**
* path relative to repository root
*/
protected abstract fun addToIndex(file: File, path: String, content: ByteArray, size: Int)
protected abstract fun addToIndex(file: Path, path: String, content: ByteArray, size: Int)
override fun delete(path: String) {
LOG.debug { "Remove $path"}
lock.write {
val file = File(dir, path)
val file = dir.resolve(path)
// delete could be called for non-existent file
if (file.exists()) {
delete(file, path)
@@ -151,25 +142,26 @@ abstract class BaseRepositoryManager(protected val dir: File) : RepositoryManage
}
}
private fun delete(file: File, path: String) {
val isFile = file.isFile
private fun delete(file: Path, path: String) {
val isFile = file.isFile()
file.removeWithParentsIfEmpty(dir, isFile)
deleteFromIndex(path, isFile)
}
protected abstract fun deleteFromIndex(path: String, isFile: Boolean)
override fun has(path: String) = lock.read { File(dir, path).exists() }
override fun has(path: String) = lock.read { dir.resolve(path).exists() }
}
fun File.removeWithParentsIfEmpty(root: File, isFile: Boolean = true) {
FileUtil.delete(this)
fun Path.removeWithParentsIfEmpty(root: Path, isFile: Boolean = true) {
delete()
if (isFile) {
// remove empty directories
var parent = this.parentFile
while (parent != null && parent != root && parent.delete()) {
parent = parent.parentFile
var parent = this.parent
while (parent != null && parent != root) {
parent.delete()
parent = parent.parent
}
}
}
+13 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,8 @@ import com.intellij.openapi.util.AtomicNotNullLazyValue
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.SingleAlarm
import com.intellij.util.SystemProperties
import com.intellij.util.exists
import com.intellij.util.move
import org.jetbrains.keychain.CredentialsStore
import org.jetbrains.keychain.FileCredentialsStore
import org.jetbrains.keychain.OsXCredentialsStore
@@ -40,11 +42,12 @@ import org.jetbrains.keychain.isOSXCredentialsStoreSupported
import org.jetbrains.settingsRepository.git.GitRepositoryManager
import org.jetbrains.settingsRepository.git.GitRepositoryService
import org.jetbrains.settingsRepository.git.processChildren
import java.io.File
import java.io.InputStream
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.properties.Delegates
val PLUGIN_NAME: String = "Settings Repository"
internal const val PLUGIN_NAME: String = "Settings Repository"
internal val LOG: Logger = Logger.getInstance(IcsManager::class.java)
@@ -52,7 +55,7 @@ val icsManager by lazy(LazyThreadSafetyMode.NONE) {
ApplicationLoadListener.EP_NAME.findExtension(IcsApplicationLoadListener::class.java).icsManager
}
class IcsManager(dir: File) {
class IcsManager(dir: Path) {
val credentialsStore = object : AtomicNotNullLazyValue<CredentialsStore>() {
override fun compute(): CredentialsStore {
if (isOSXCredentialsStoreSupported && SystemProperties.getBooleanProperty("ics.use.osx.keychain", true)) {
@@ -63,14 +66,14 @@ class IcsManager(dir: File) {
LOG.error(e)
}
}
return FileCredentialsStore(File(dir, ".git_auth"))
return FileCredentialsStore(dir.resolve(".git_auth"))
}
}
val settingsFile = File(dir, "config.json")
val settingsFile = dir.resolve("config.json")
val settings: IcsSettings
val repositoryManager: RepositoryManager = GitRepositoryManager(credentialsStore, File(dir, "repository"))
val repositoryManager: RepositoryManager = GitRepositoryManager(credentialsStore, dir.resolve("repository"))
init {
try {
@@ -226,14 +229,14 @@ class IcsApplicationLoadListener : ApplicationLoadListener {
}
val customPath = System.getProperty("ics.settingsRepository")
val pluginSystemDir = if (customPath == null) File(configPath, "settingsRepository") else File(FileUtil.expandUserHome(customPath))
val pluginSystemDir = if (customPath == null) Paths.get(configPath, "settingsRepository") else Paths.get(FileUtil.expandUserHome(customPath))
icsManager = IcsManager(pluginSystemDir)
if (!pluginSystemDir.exists()) {
try {
val oldPluginDir = File(PathManager.getSystemPath(), "settingsRepository")
val oldPluginDir = Paths.get(PathManager.getSystemPath(), "settingsRepository")
if (oldPluginDir.exists()) {
FileUtil.rename(oldPluginDir, pluginSystemDir)
oldPluginDir.move(pluginSystemDir)
}
}
catch (e: Throwable) {
@@ -16,12 +16,13 @@
package org.jetbrains.settingsRepository
import com.intellij.util.SmartList
import com.intellij.util.exists
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import org.jetbrains.annotations.TestOnly
import java.io.File
import java.nio.file.Path
class ReadOnlySourcesManager(private val settings: IcsSettings, val rootDir: File) {
class ReadOnlySourcesManager(private val settings: IcsSettings, val rootDir: Path) {
private var _repositories: List<Repository>? = null
val repositories: List<Repository>
@@ -36,9 +37,9 @@ class ReadOnlySourcesManager(private val settings: IcsSettings, val rootDir: Fil
for (source in settings.readOnlySources) {
try {
val path = source.path ?: continue
val dir = File(rootDir, path)
val dir = rootDir.resolve(path)
if (dir.exists()) {
r.add(FileRepositoryBuilder().setBare().setGitDir(dir).build())
r.add(FileRepositoryBuilder().setBare().setGitDir(dir.toFile()).build())
}
else {
LOG.warn("Skip read-only source ${source.url} because dir doesn't exists")
@@ -59,5 +60,5 @@ class ReadOnlySourcesManager(private val settings: IcsSettings, val rootDir: Fil
_repositories = null
}
@TestOnly fun sourceToDir(source: ReadonlySource) = File(rootDir, source.path!!)
@TestOnly fun sourceToDir(source: ReadonlySource) = rootDir.resolve(source.path!!)
}
@@ -16,13 +16,16 @@
package org.jetbrains.settingsRepository
import com.intellij.openapi.ui.Messages
import com.intellij.util.exists
import com.intellij.util.io.URLUtil
import com.intellij.util.isDirectory
import org.eclipse.jgit.lib.Constants
import org.eclipse.jgit.transport.URIish
import org.jetbrains.settingsRepository.git.createBareRepository
import java.awt.Container
import java.io.File
import java.io.IOException
import java.nio.file.Path
import java.nio.file.Paths
interface RepositoryService {
fun checkUrl(uriString: String, messageParent: Container? = null): Boolean {
@@ -43,9 +46,9 @@ interface RepositoryService {
fun checkFileRepo(url: String, messageParent: Container): Boolean {
val suffix = "/${Constants.DOT_GIT}"
val file = File(if (url.endsWith(suffix)) url.substring(0, url.length - suffix.length) else url)
val file = Paths.get(if (url.endsWith(suffix)) url.substring(0, url.length - suffix.length) else url)
if (file.exists()) {
if (!file.isDirectory) {
if (!file.isDirectory()) {
//noinspection DialogTitleCapitalization
Messages.showErrorDialog(messageParent, "Specified path is not a directory", "Specified Path is Invalid")
return false
@@ -75,5 +78,5 @@ interface RepositoryService {
}
// must be protected, kotlin bug
fun isValidRepository(file: File): Boolean
fun isValidRepository(file: Path): Boolean
}
@@ -23,6 +23,7 @@ import com.intellij.ide.actions.getExportableComponentsMap
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.stateStore
import com.intellij.util.directoryStreamIfExists
import com.intellij.util.isFile
import com.intellij.util.systemIndependentPath
import java.nio.file.Files
@@ -55,19 +56,16 @@ fun copyLocalConfig(storageManager: StateStorageManagerImpl = ApplicationManager
}
private fun saveDirectory(parent: Path, parentFileSpec: String, roamingType: RoamingType, streamProvider: IcsManager.IcsStreamProvider) {
if (!Files.isDirectory(parent)) {
return
}
for (file in Files.newDirectoryStream(parent)) {
val childFileSpec = "$parentFileSpec/${file.fileName}"
if (file.isFile()) {
val fileBytes = Files.readAllBytes(file)
streamProvider.doSave(childFileSpec, fileBytes, fileBytes.size, roamingType)
}
else {
saveDirectory(file, childFileSpec, roamingType, streamProvider)
parent.directoryStreamIfExists {
for (file in it) {
val childFileSpec = "$parentFileSpec/${file.fileName}"
if (file.isFile()) {
val fileBytes = Files.readAllBytes(file)
streamProvider.doSave(childFileSpec, fileBytes, fileBytes.size, roamingType)
}
else {
saveDirectory(file, childFileSpec, roamingType, streamProvider)
}
}
}
}
+6 -6
View File
@@ -39,8 +39,8 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter
import org.jetbrains.keychain.CredentialsStore
import org.jetbrains.settingsRepository.AuthenticationException
import org.jetbrains.settingsRepository.LOG
import java.io.File
import java.io.InputStream
import java.nio.file.Path
fun wrapIfNeedAndReThrow(e: TransportException) {
if (e is org.eclipse.jgit.errors.NoRemoteRepositoryException || e.status == TransportException.Status.CANNOT_RESOLVE_REPO) {
@@ -91,14 +91,14 @@ fun Repository.disableAutoCrLf(): Repository {
return this
}
fun createBareRepository(dir: File): Repository {
val repository = FileRepositoryBuilder().setBare().setGitDir(dir).build()
fun createBareRepository(dir: Path): Repository {
val repository = FileRepositoryBuilder().setBare().setGitDir(dir.toFile()).build()
repository.create(true)
return repository
}
fun createRepository(dir: File): Repository {
val repository = FileRepositoryBuilder().setWorkTree(dir).build()
fun createRepository(dir: Path): Repository {
val repository = FileRepositoryBuilder().setWorkTree(dir.toFile()).build()
repository.create()
return repository
}
@@ -165,7 +165,7 @@ fun Repository.computeIndexDiff(): IndexDiff {
}
}
fun cloneBare(uri: String, dir: File, credentialsStore: NotNullLazyValue<CredentialsStore>? = null, progressMonitor: ProgressMonitor = NullProgressMonitor.INSTANCE): Repository {
fun cloneBare(uri: String, dir: Path, credentialsStore: NotNullLazyValue<CredentialsStore>? = null, progressMonitor: ProgressMonitor = NullProgressMonitor.INSTANCE): Repository {
val repository = createBareRepository(dir)
val config = repository.setUpstream(uri)
val remoteConfig = RemoteConfig(config, Constants.DEFAULT_REMOTE_NAME)
@@ -20,9 +20,8 @@ import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.util.NotNullLazyValue
import com.intellij.openapi.util.ShutDownTracker
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.util.SmartList
import com.intellij.util.*
import org.eclipse.jgit.api.AddCommand
import org.eclipse.jgit.api.errors.NoHeadException
import org.eclipse.jgit.api.errors.UnmergedPathsException
@@ -41,16 +40,17 @@ import org.jetbrains.jgit.dirCache.edit
import org.jetbrains.keychain.CredentialsStore
import org.jetbrains.settingsRepository.*
import org.jetbrains.settingsRepository.RepositoryManager.Updater
import java.io.File
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Path
import kotlin.concurrent.write
class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<CredentialsStore>, dir: File) : BaseRepositoryManager(dir) {
class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<CredentialsStore>, dir: Path) : BaseRepositoryManager(dir) {
val repository: Repository
get() {
var r = _repository
if (r == null) {
r = FileRepositoryBuilder().setWorkTree(dir).build()
r = FileRepositoryBuilder().setWorkTree(dir.toFile()).build()
_repository = r
if (ApplicationManager.getApplication()?.isUnitTestMode != true) {
ShutDownTracker.getInstance().registerShutdownTask { _repository?.close() }
@@ -103,7 +103,7 @@ class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<Creden
override fun isRepositoryExists(): Boolean {
val repo = _repository
if (repo == null) {
return dir.exists() && FileRepositoryBuilder().setWorkTree(dir).setup().objectDirectory.exists()
return dir.exists() && FileRepositoryBuilder().setWorkTree(dir.toFile()).setup().objectDirectory.exists()
}
else {
return repo.objectDatabase.exists()
@@ -112,8 +112,8 @@ class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<Creden
override fun hasUpstream() = getUpstream() != null
override fun addToIndex(file: File, path: String, content: ByteArray, size: Int) {
repository.edit(AddLoadedFile(path, content, size, file.lastModified()))
override fun addToIndex(file: Path, path: String, content: ByteArray, size: Int) {
repository.edit(AddLoadedFile(path, content, size, file.lastModified().toMillis()))
}
override fun deleteFromIndex(path: String, isFile: Boolean) {
@@ -239,27 +239,25 @@ class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<Creden
var addCommand: AddCommand? = null
val toDelete = SmartList<DeleteDirectory>()
for ((oldPath, newPath) in pairs) {
val old = File(dir, oldPath)
val old = dir.resolve(oldPath)
if (!old.exists()) {
continue
}
LOG.info("Rename $oldPath to $newPath")
val files = old.listFiles()
if (files != null) {
val new = if (newPath == null) dir else File(dir, newPath)
for (file in files) {
old.directoryStreamIfExists {
val new = if (newPath == null) dir else dir.resolve(newPath)
for (file in it) {
try {
if (file.isHidden) {
FileUtil.delete(file)
if (file.isHidden()) {
file.delete()
}
else {
file.renameTo(File(new, file.name))
Files.move(file, new.resolve(file.fileName))
if (addCommand == null) {
addCommand = AddCommand(repository)
}
addCommand.addFilepattern(if (newPath == null) file.name else "$newPath/${file.name}")
addCommand!!.addFilepattern(if (newPath == null) file.fileName.toString() else "$newPath/${file.fileName}")
}
}
catch (e: Throwable) {
@@ -270,7 +268,7 @@ class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<Creden
}
try {
FileUtil.delete(old)
old.deleteRecursively()
}
catch (e: Throwable) {
LOG.error(e)
@@ -283,7 +281,7 @@ class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<Creden
repository.edit(toDelete)
if (addCommand != null) {
addCommand.call()
addCommand!!.call()
}
repository.commit(with(IdeaCommitMessageFormatter()) { StringBuilder().appendCommitOwnerInfo(true) }.append("Get rid of \$ROOT_CONFIG$ and \$APP_CONFIG").toString())
@@ -293,7 +291,7 @@ class GitRepositoryManager(private val credentialsStore: NotNullLazyValue<Creden
private fun getIgnoreRules(): IgnoreNode? {
var node = ignoreRules
if (node == null) {
val file = File(dir, Constants.DOT_GIT_IGNORE)
val file = dir.resolve(Constants.DOT_GIT_IGNORE)
if (file.exists()) {
node = IgnoreNode()
file.inputStream().use { node!!.parse(it) }
@@ -319,14 +317,14 @@ fun printMessages(fetchResult: OperationResult) {
}
class GitRepositoryService : RepositoryService {
override fun isValidRepository(file: File): Boolean {
if (File(file, Constants.DOT_GIT).exists()) {
override fun isValidRepository(file: Path): Boolean {
if (file.resolve(Constants.DOT_GIT).exists()) {
return true
}
// existing bare repository
try {
FileRepositoryBuilder().setGitDir(file).setMustExist(true).build()
FileRepositoryBuilder().setGitDir(file.toFile()).setMustExist(true).build()
}
catch (e: IOException) {
return false
@@ -17,6 +17,7 @@ package org.jetbrains.jgit.dirCache
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.exists
import org.eclipse.jgit.dircache.BaseDirCacheEditor
import org.eclipse.jgit.dircache.DirCache
import org.eclipse.jgit.dircache.DirCacheEntry
@@ -252,8 +253,8 @@ fun Repository.deletePath(path: String, isFile: Boolean = true, fromWorkingTree:
edit((if (isFile) DeleteFile(path) else DeleteDirectory(path)))
if (fromWorkingTree) {
val workTree = workTree
val ioFile = File(workTree, path)
val workTree = workTree.toPath()
val ioFile = workTree.resolve(path)
if (ioFile.exists()) {
ioFile.removeWithParentsIfEmpty(workTree, isFile)
}
@@ -1,11 +1,32 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* 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 org.jetbrains.keychain
import com.intellij.openapi.util.PasswordUtil
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.delete
import com.intellij.util.exists
import com.intellij.util.inputStream
import com.intellij.util.io.IOUtil
import java.io.*
import com.intellij.util.outputStream
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.IOException
import java.nio.file.Path
class FileCredentialsStore(private val storeFile: File) : CredentialsStore {
class FileCredentialsStore(private val storeFile: Path) : CredentialsStore {
// we store only one for any URL, don't want to add complexity, OS keychain should be used
private var credentials: Credentials? = null
@@ -20,7 +41,7 @@ class FileCredentialsStore(private val storeFile: File) : CredentialsStore {
if (storeFile.exists()) {
try {
var hasErrors = true
val `in` = DataInputStream(FileInputStream(storeFile).buffered())
val `in` = DataInputStream(storeFile.inputStream().buffered())
try {
credentials = Credentials(PasswordUtil.decodePassword(IOUtil.readString(`in`)), PasswordUtil.decodePassword(IOUtil.readString(`in`)))
hasErrors = false
@@ -61,8 +82,7 @@ class FileCredentialsStore(private val storeFile: File) : CredentialsStore {
this.credentials = credentials
try {
FileUtil.createParentDirs(storeFile)
val out = DataOutputStream(FileOutputStream(storeFile).buffered())
val out = DataOutputStream(storeFile.outputStream().buffered())
try {
IOUtil.writeString(PasswordUtil.encodePassword(credentials.id), out)
IOUtil.writeString(PasswordUtil.encodePassword(credentials.token), out)
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,10 +23,8 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectWriter
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.PathUtilRt
import com.intellij.util.SmartList
import com.intellij.util.Time
import java.io.File
import com.intellij.util.*
import java.nio.file.Path
private val DEFAULT_COMMIT_DELAY = 10 * Time.MINUTE
@@ -59,22 +57,22 @@ class MyPrettyPrinter : DefaultPrettyPrinter() {
}
}
fun saveSettings(settings: IcsSettings, settingsFile: File) {
fun saveSettings(settings: IcsSettings, settingsFile: Path) {
val serialized = ObjectMapper().writer<ObjectWriter>(MyPrettyPrinter()).writeValueAsBytes(settings)
if (serialized.size <= 2) {
FileUtil.delete(settingsFile)
settingsFile.delete()
}
else {
FileUtil.writeToFile(settingsFile, serialized)
settingsFile.write(serialized)
}
}
fun loadSettings(settingsFile: File): IcsSettings {
fun loadSettings(settingsFile: Path): IcsSettings {
if (!settingsFile.exists()) {
return IcsSettings()
}
val settings = ObjectMapper().readValue(settingsFile, IcsSettings::class.java)
val settings = ObjectMapper().readValue(settingsFile.toFile(), IcsSettings::class.java)
if (settings.commitDelay <= 0) {
settings.commitDelay = DEFAULT_COMMIT_DELAY
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,17 +23,17 @@ import com.intellij.openapi.progress.Task
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.ui.TextBrowseFolderListener
import com.intellij.openapi.ui.TextFieldWithBrowseButton
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.ui.DocumentAdapter
import com.intellij.util.Function
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.deleteRecursively
import com.intellij.util.exists
import com.intellij.util.ui.FormBuilder
import com.intellij.util.ui.table.TableModelEditor
import gnu.trove.THashSet
import org.jetbrains.settingsRepository.git.asProgressMonitor
import org.jetbrains.settingsRepository.git.cloneBare
import java.io.File
import javax.swing.JTextField
import javax.swing.event.DocumentEvent
@@ -130,7 +130,7 @@ internal fun createReadOnlySourcesEditor(): ConfigurableUi<IcsSettings> {
indicator.checkCanceled()
try {
indicator.text2 = path
FileUtil.delete(File(root, path))
root.resolve(path).deleteRecursively()
}
catch (e: Exception) {
LOG.error(e)
@@ -143,9 +143,9 @@ internal fun createReadOnlySourcesEditor(): ConfigurableUi<IcsSettings> {
indicator.checkCanceled()
try {
indicator.text = "Cloning ${StringUtil.trimMiddle(source.url!!, 255)}"
val dir = File(root, source.path!!)
val dir = root.resolve(source.path!!)
if (dir.exists()) {
FileUtil.delete(dir)
dir.deleteRecursively()
}
cloneBare(source.url!!, dir, icsManager.credentialsStore, indicator.asProgressMonitor()).close()
}
@@ -31,7 +31,7 @@ internal class BareGitTest {
@Rule fun getTemporaryFolder() = tempDirManager
@Test fun `remote doesn't have commits`() {
val repository = cloneBare(tempDirManager.createRepository("remote").workTree.absolutePath, tempDirManager.newDirectory("local"))
val repository = cloneBare(tempDirManager.createRepository("remote").workTree.absolutePath, tempDirManager.newPath("local"))
assertThat(repository.read("\$ROOT_CONFIG$/keymaps/Mac OS X from RubyMine.xml")).isNull()
}
@@ -41,7 +41,7 @@ internal class BareGitTest {
remoteRepository.add(filePath, SAMPLE_FILE_CONTENT)
remoteRepository.commit("")
val repository = cloneBare(remoteRepository.workTree.absolutePath, tempDirManager.newDirectory())
val repository = cloneBare(remoteRepository.workTree.absolutePath, tempDirManager.newPath())
assertThat(FileUtil.loadTextAndClose(repository.read(filePath)!!)).isEqualTo(SAMPLE_FILE_CONTENT)
}
@@ -52,7 +52,7 @@ internal class BareGitTest {
remoteRepository.add(filePath, SAMPLE_FILE_CONTENT)
remoteRepository.commit("")
val repository = cloneBare(remoteRepository.workTree.absolutePath, tempDirManager.newDirectory())
val repository = cloneBare(remoteRepository.workTree.absolutePath, tempDirManager.newPath())
val data = THashMap<String, String>()
repository.processChildren("keymaps") {name, input ->
@@ -18,12 +18,11 @@ class CredentialsTest {
private var storeFile: File? = null
private fun createProvider(credentialsStore: CredentialsStore): JGitCredentialsProvider {
return JGitCredentialsProvider(NotNullLazyValue.createConstantValue<CredentialsStore>(credentialsStore), FileRepositoryBuilder().setBare().setGitDir(File("/tmp/fake")).build())
return JGitCredentialsProvider(NotNullLazyValue.createConstantValue(credentialsStore), FileRepositoryBuilder().setBare().setGitDir(File("/tmp/fake")).build())
}
private fun createFileStore(): FileCredentialsStore {
storeFile = FileUtil.generateRandomTemporaryPath()
return FileCredentialsStore(storeFile!!)
return FileCredentialsStore(FileUtil.generateRandomTemporaryPath().toPath())
}
@After fun tearDown() {
@@ -322,7 +322,7 @@ internal class GitTest : GitTestCase() {
repositoryManager.setUpstream(remoteRepository.workTree.absolutePath)
val store = ApplicationStoreImpl(ApplicationManager.getApplication()!!)
val localConfigPath = tempDirManager.newPath("local_config")
val localConfigPath = tempDirManager.newPath("local_config", refreshVfs = true)
val lafData = """<application>
<component name="UISettings">
@@ -53,7 +53,7 @@ abstract class IcsTestCase {
get() = fsRule.fs
val icsManager by lazy(LazyThreadSafetyMode.NONE) {
val icsManager = IcsManager(tempDirManager.newDirectory())
val icsManager = IcsManager(tempDirManager.newPath())
icsManager.repositoryManager.createRepositoryIfNeed()
icsManager.repositoryActive = true
icsManager
@@ -62,4 +62,4 @@ abstract class IcsTestCase {
val provider by lazy(LazyThreadSafetyMode.NONE) { icsManager.ApplicationLevelProvider() }
}
fun TemporaryDirectory.createRepository(directoryName: String? = null) = createGitRepository(newDirectory(directoryName))
fun TemporaryDirectory.createRepository(directoryName: String? = null) = createGitRepository(newPath(directoryName))
@@ -28,7 +28,6 @@ import org.jetbrains.settingsRepository.git.cloneBare
import org.jetbrains.settingsRepository.git.commit
import org.junit.ClassRule
import org.junit.Test
import java.io.File
class LoadTest : IcsTestCase() {
companion object {
@@ -38,7 +37,7 @@ class LoadTest : IcsTestCase() {
private val dirPath = "\$ROOT_CONFIG$/keymaps"
private fun createSchemeManager(dirPath: String) = SchemeManagerImpl<TestScheme, TestScheme>(dirPath, TestSchemesProcessor(), provider, tempDirManager.newDirectory("schemes"))
private fun createSchemeManager(dirPath: String) = SchemeManagerImpl<TestScheme, TestScheme>(dirPath, TestSchemesProcessor(), provider, tempDirManager.newPath("schemes"))
@Test fun `load scheme`() {
val localScheme = TestScheme("local")
@@ -112,7 +111,7 @@ class LoadTest : IcsTestCase() {
fun Repository.createAndRegisterReadOnlySource(): ReadonlySource {
val source = ReadonlySource(workTree.absolutePath)
assertThat(cloneBare(source.url!!, File(icsManager.readOnlySourcesManager.rootDir, source.path!!)).objectDatabase.exists()).isTrue()
assertThat(cloneBare(source.url!!, icsManager.readOnlySourcesManager.rootDir.resolve(source.path!!)).objectDatabase.exists()).isTrue()
icsManager.readOnlySourcesManager.setSources(listOf(source))
return source
}
@@ -1,11 +1,10 @@
package org.jetbrains.settingsRepository.test
import com.intellij.testFramework.file
import com.intellij.util.isDirectory
import com.intellij.util.directoryStreamIfExists
import com.intellij.util.readBytes
import org.jetbrains.settingsRepository.SyncType
import org.junit.Test
import java.nio.file.Files
// empty means "no files, no HEAD, no commits"
internal class OverwriteRemote : GitTestCase() {
@@ -37,8 +36,8 @@ internal class OverwriteRemote : GitTestCase() {
configureLocalRepository()
val root = fs.getPath("/")
if (root.isDirectory()) {
for (path in Files.newDirectoryStream(root)) {
root.directoryStreamIfExists {
for (path in it) {
provider.write(path.toString().substring(1), path.readBytes())
}
repositoryManager.commit()