IDEA-143759 Repository contains unmerged paths. Merge not work for me

This commit is contained in:
Vladimir Krivosheev
2015-08-25 13:45:42 +02:00
parent 75f7c3e251
commit c12f1a627b
7 changed files with 194 additions and 101 deletions
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2015 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.settingsRepository
import com.intellij.openapi.application.ApplicationManager
@@ -6,18 +21,15 @@ 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.MergeSession
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 org.jetbrains.annotations.TestOnly
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.io.OutputStream
import java.util.Arrays
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
@@ -158,38 +170,25 @@ fun File.removeWithParentsIfEmpty(root: File, isFile: Boolean = true) {
}
}
}
// kotlin bug, cannot be val (.NoSuchMethodError: org.jetbrains.settingsRepository.SettingsRepositoryPackage.getMARKER_ACCEPT_MY()[B)
TestOnly object AM {
val MARKER_ACCEPT_MY: ByteArray = "__accept my__".toByteArray()
val MARKER_ACCEPT_THEIRS: ByteArray = "__accept theirs__".toByteArray()
}
var conflictResolver: ((files: List<VirtualFile>, mergeProvider: MergeProvider2) -> Unit)? = null
fun resolveConflicts(files: List<VirtualFile>, mergeProvider: MergeProvider2): List<VirtualFile> {
if (ApplicationManager.getApplication()!!.isUnitTestMode()) {
val mergeSession = mergeProvider.createMergeSession(files)
for (file in files) {
val mergeData = mergeProvider.loadRevisions(file)
if (Arrays.equals(mergeData.CURRENT, AM.MARKER_ACCEPT_MY) || Arrays.equals(mergeData.LAST, AM.MARKER_ACCEPT_THEIRS)) {
mergeSession.conflictResolvedForFile(file, MergeSession.Resolution.AcceptedYours)
}
else if (Arrays.equals(mergeData.CURRENT, AM.MARKER_ACCEPT_THEIRS) || Arrays.equals(mergeData.LAST, AM.MARKER_ACCEPT_MY)) {
mergeSession.conflictResolvedForFile(file, MergeSession.Resolution.AcceptedTheirs)
}
else if (Arrays.equals(mergeData.LAST, AM.MARKER_ACCEPT_MY)) {
file.setBinaryContent(mergeData.LAST!!)
mergeProvider.conflictResolvedForFile(file)
}
else {
throw UnsupportedOperationException()
}
if (conflictResolver == null) {
throw CannotResolveConflictInTestMode()
}
else {
conflictResolver!!(files, mergeProvider)
}
return files
}
var processedFiles: List<VirtualFile>? = null
invokeAndWaitIfNeed {
val fileMergeDialog = MultipleFileMergeDialog(null, files, mergeProvider, MergeDialogCustomizer())
val fileMergeDialog = MultipleFileMergeDialog(null, files, mergeProvider, object : MergeDialogCustomizer() {
override fun getMultipleFileDialogTitle() = "Settings Repository: Files Merged with Conflicts"
})
fileMergeDialog.show()
processedFiles = fileMergeDialog.getProcessedFiles()
}
@@ -289,6 +289,4 @@ class IcsApplicationLoadListener : ApplicationLoadListener {
icsManager.beforeApplicationLoaded(application)
}
}
class NoRemoteRepositoryException(cause: Throwable) : RuntimeException(cause.getMessage(), cause)
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2015 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.settingsRepository.git
import com.intellij.openapi.fileEditor.FileDocumentManager
@@ -6,9 +21,8 @@ import com.intellij.openapi.vcs.merge.MergeProvider2
import com.intellij.openapi.vcs.merge.MergeSession
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.ArrayUtil
import com.intellij.util.ui.ColumnInfo
import org.eclipse.jgit.diff.RawText
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.lib.Repository
import org.jetbrains.jgit.dirCache.deletePath
import org.jetbrains.jgit.dirCache.writePath
@@ -16,7 +30,7 @@ import org.jetbrains.settingsRepository.RepositoryVirtualFile
import java.nio.CharBuffer
import java.util.ArrayList
private fun conflictsToVirtualFiles(map: Map<String, org.eclipse.jgit.merge.MergeResult<*>>): MutableList<VirtualFile> {
private fun conflictsToVirtualFiles(map: Map<String, Any>): MutableList<VirtualFile> {
val result = ArrayList<VirtualFile>(map.size())
for (path in map.keySet()) {
result.add(RepositoryVirtualFile(path))
@@ -24,7 +38,12 @@ private fun conflictsToVirtualFiles(map: Map<String, org.eclipse.jgit.merge.Merg
return result
}
class JGitMergeProvider(private val repository: Repository, private val myCommit: ObjectId, private val theirsCommit: ObjectId, private val conflicts: Map<String, org.eclipse.jgit.merge.MergeResult<*>>) : MergeProvider2 {
/**
* If content null:
* Ours or Theirs - deleted.
* Base - missed (no base).
*/
class JGitMergeProvider<T>(private val repository: Repository, private val conflicts: Map<String, T>, private val pathToContent: Map<String, T>.(path: String, index: Int) -> ByteArray?) : MergeProvider2 {
override fun createMergeSession(files: List<VirtualFile>) = JGitMergeSession()
override fun conflictResolvedForFile(file: VirtualFile) {
@@ -42,22 +61,23 @@ class JGitMergeProvider(private val repository: Repository, private val myCommit
}
}
// cannot be private due to Kotlin bug
fun addFile(bytes: ByteArray, file: VirtualFile, size: Int = bytes.size()) {
private fun addFile(bytes: ByteArray, file: VirtualFile, size: Int = bytes.size()) {
repository.writePath(file.getPath(), bytes, size)
}
override fun isBinary(file: VirtualFile) = file.getFileType().isBinary()
override fun loadRevisions(file: VirtualFile): MergeData {
val sequences = conflicts[file.getPath()]!!.getSequences()
val path = file.getPath()
val mergeData = MergeData()
mergeData.ORIGINAL = (sequences[0] as RawText).getContent()
mergeData.CURRENT = (sequences[1] as RawText).getContent()
mergeData.LAST = (sequences[2] as RawText).getContent()
mergeData.ORIGINAL = getContentOrEmpty(path, 0)
mergeData.CURRENT = getContentOrEmpty(path, 1)
mergeData.LAST = getContentOrEmpty(path, 2)
return mergeData
}
private fun getContentOrEmpty(path: String, index: Int) = conflicts.pathToContent(path, index) ?: ArrayUtil.EMPTY_BYTE_ARRAY
private inner class JGitMergeSession : MergeSession {
override fun getMergeInfoColumns(): Array<ColumnInfo<out Any?, out Any?>> {
return arrayOf(StatusColumn(false), StatusColumn(true))
@@ -71,19 +91,19 @@ class JGitMergeProvider(private val repository: Repository, private val myCommit
}
else {
val content = getContent(file, resolution == MergeSession.Resolution.AcceptedTheirs)
if (content == RawText.EMPTY_TEXT) {
if (content == null) {
repository.deletePath(file.getPath())
}
else {
addFile(content.getContent(), file)
addFile(content, file)
}
}
}
private fun getContent(file: VirtualFile, isTheirs: Boolean) = conflicts[file.getPath()]!!.getSequences()[if (isTheirs) 2 else 1] as RawText
private fun getContent(file: VirtualFile, isTheirs: Boolean) = conflicts.pathToContent(file.getPath(), if (isTheirs) 2 else 1)
inner class StatusColumn(private val isTheirs: Boolean) : ColumnInfo<VirtualFile, String>(if (isTheirs) "Theirs" else "Yours") {
override fun valueOf(file: VirtualFile?) = if (getContent(file!!, isTheirs) == RawText.EMPTY_TEXT) "Deleted" else "Modified"
override fun valueOf(file: VirtualFile?) = if (getContent(file!!, isTheirs) == null) "Deleted" else "Modified"
override fun getMaxStringValue() = "Modified"
+69 -45
View File
@@ -17,6 +17,8 @@ package org.jetbrains.settingsRepository.git
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.SmartList
import com.intellij.util.containers.hash.LinkedHashMap
import org.eclipse.jgit.api.MergeCommand.FastForwardMode
import org.eclipse.jgit.api.MergeResult
import org.eclipse.jgit.api.MergeResult.MergeStatus
@@ -24,6 +26,8 @@ import org.eclipse.jgit.api.errors.CheckoutConflictException
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException
import org.eclipse.jgit.api.errors.JGitInternalException
import org.eclipse.jgit.api.errors.NoHeadException
import org.eclipse.jgit.diff.RawText
import org.eclipse.jgit.diff.Sequence
import org.eclipse.jgit.dircache.DirCacheCheckout
import org.eclipse.jgit.internal.JGitText
import org.eclipse.jgit.lib.*
@@ -38,7 +42,6 @@ import org.eclipse.jgit.treewalk.FileTreeIterator
import org.jetbrains.settingsRepository.*
import java.io.IOException
import java.text.MessageFormat
import java.util.ArrayList
open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndicator?, val commitMessageFormatter: CommitMessageFormatter = IdeaCommitMessageFormatter()) {
val repository = manager.repository
@@ -53,13 +56,30 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
LOG.debug("Pull")
val repository = manager.repository
val repositoryState = repository.getRepositoryState()
var repositoryState = repository.getRepositoryState()
if (repositoryState == RepositoryState.MERGING) {
val conflicts = LinkedHashMap<String, Array<ByteArray?>>()
val dirCache = repository.readDirCache()
val reader = repository.newObjectReader()
reader.use {
for (i in 0..(dirCache.getEntryCount() - 1)) {
val entry = dirCache.getEntry(i)
if (!entry.isMerged()) {
conflicts.getOrPut(entry.getPathString(), { arrayOfNulls<ByteArray>(3) })[entry.getStage() - 1] = reader.open(entry.getObjectId(), Constants.OBJ_BLOB).getCachedBytes()
}
}
}
resolveConflicts(JGitMergeProvider(repository, conflicts, { path, index -> get(path)!!.get(index) }), conflictsToVirtualFiles(conflicts), repository)
// compute new state
repositoryState = repository.getRepositoryState()
}
if (repositoryState != RepositoryState.SAFE) {
LOG.warn(MessageFormat.format(JGitText.get().cannotPullOnARepoWithState, repositoryState.name()))
}
val refToMerge = prefetchedRefToMerge ?: fetch() ?: return null
var refToMerge = prefetchedRefToMerge ?: fetch() ?: return null
val mergeResult = merge(refToMerge, mergeStrategy, commitMessage = commitMessage)
val mergeStatus = mergeResult.mergeStatus
if (LOG.isDebugEnabled()) {
@@ -67,31 +87,7 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
}
if (mergeStatus == MergeStatus.CONFLICTING) {
val mergedCommits = mergeResult.mergedCommits
assert(mergedCommits.size() == 2)
val conflicts = mergeResult.conflicts!!
var unresolvedFiles = conflictsToVirtualFiles(conflicts)
val mergeProvider = JGitMergeProvider(repository, mergedCommits[0]!!, mergedCommits[1]!!, conflicts)
val resolvedFiles: List<VirtualFile>
val mergedFiles = ArrayList<String>()
while (true) {
resolvedFiles = resolveConflicts(unresolvedFiles, mergeProvider)
for (file in resolvedFiles) {
mergedFiles.add(file.getPath())
}
if (resolvedFiles.size() == unresolvedFiles.size()) {
break
}
else {
unresolvedFiles.removeAll(mergedFiles)
}
}
repository.commit()
return mergeResult.result.toMutable().addChanged(mergedFiles)
return resolveConflicts(mergeResult, repository)
}
else if (!mergeStatus.isSuccessful()) {
throw IllegalStateException(mergeResult.toString())
@@ -104,9 +100,7 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
fun fetch(prevRefUpdateResult: RefUpdate.Result? = null): Ref? {
indicator?.checkCanceled()
val repository = manager.repository
val fetchResult = repository.fetch(remoteConfig, manager.credentialsProvider, indicator.asProgressMonitor()) ?: return null
val fetchResult = manager.repository.fetch(remoteConfig, manager.credentialsProvider, indicator.asProgressMonitor()) ?: return null
if (LOG.isDebugEnabled()) {
printMessages(fetchResult)
@@ -129,10 +123,10 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
// we can have more than one fetch ref spec, but currently we don't worry about it
if (refUpdateResult == RefUpdate.Result.LOCK_FAILURE || refUpdateResult == RefUpdate.Result.IO_FAILURE) {
if (prevRefUpdateResult == refUpdateResult) {
throw IOException("Ref update result " + refUpdateResult.name() + ", we have already tried to fetch again, but no luck")
throw IOException("Ref update result ${refUpdateResult.name()}, we have already tried to fetch again, but no luck")
}
LOG.warn("Ref update result " + refUpdateResult.name() + ", trying again after 500 ms")
LOG.warn("Ref update result ${refUpdateResult.name()}, trying again after 500 ms")
Thread.sleep(500)
return fetch(refUpdateResult)
}
@@ -165,17 +159,13 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
val head = repository.getRef(Constants.HEAD) ?: throw NoHeadException(JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported)
// handle annotated tags
val ref = repository.peel(unpeeledRef)
val objectId = ref.getPeeledObjectId() ?: ref.getObjectId()
// Check for FAST_FORWARD, ALREADY_UP_TO_DATE
val revWalk = RevWalk(repository)
var dirCacheCheckout: DirCacheCheckout? = null
try {
// handle annotated tags
val ref = repository.peel(unpeeledRef)
var objectId = ref.getPeeledObjectId()
if (objectId == null) {
objectId = ref.getObjectId()
}
val srcCommit = revWalk.lookupCommit(objectId)
val headId = head.getObjectId()
if (headId == null) {
@@ -235,11 +225,11 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
else {
mergeMessage = commitMessageFormatter.mergeMessage(listOf(ref), head)
repository.writeMergeCommitMsg(mergeMessage)
repository.writeMergeHeads(arrayListOf(ref.getObjectId()))
repository.writeMergeHeads(listOf(ref.getObjectId()))
}
val merger = mergeStrategy.newMerger(repository)
val noProblems: Boolean
var lowLevelResults: Map<String, org.eclipse.jgit.merge.MergeResult<*>>? = null
var lowLevelResults: Map<String, org.eclipse.jgit.merge.MergeResult<out Sequence>>? = null
var failingPaths: Map<String, ResolveMerger.MergeFailureReason>? = null
var unmergedPaths: List<String>? = null
if (merger is ResolveMerger) {
@@ -297,7 +287,7 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
}
}
catch (e: org.eclipse.jgit.errors.CheckoutConflictException) {
throw CheckoutConflictException(if (dirCacheCheckout == null) listOf<String>() else dirCacheCheckout.getConflicts(), e)
throw CheckoutConflictException(dirCacheCheckout?.getConflicts() ?: listOf(), e)
}
finally {
revWalk.close()
@@ -305,7 +295,7 @@ open class Pull(val manager: GitRepositoryManager, val indicator: ProgressIndica
}
}
class MergeResultEx(val newHead: ObjectId?, val mergeStatus: MergeStatus, val mergedCommits: Array<ObjectId?>, val result: ImmutableUpdateResult, val conflicts: Map<String, org.eclipse.jgit.merge.MergeResult<*>>? = null)
class MergeResultEx(val newHead: ObjectId?, val mergeStatus: MergeStatus, val mergedCommits: Array<ObjectId?>, val result: ImmutableUpdateResult, val conflicts: Map<String, org.eclipse.jgit.merge.MergeResult<out Sequence>>? = null)
private fun updateHead(refLogMessage: StringBuilder, newHeadId: ObjectId, oldHeadID: ObjectId, repository: Repository) {
val refUpdate = repository.updateRef(Constants.HEAD)
@@ -320,3 +310,37 @@ private fun updateHead(refLogMessage: StringBuilder, newHeadId: ObjectId, oldHea
}
}
private fun resolveConflicts(mergeResult: MergeResultEx, repository: Repository): MutableUpdateResult {
assert(mergeResult.mergedCommits.size() == 2)
val conflicts = mergeResult.conflicts!!
val mergeProvider = JGitMergeProvider(repository, conflicts, { path, index ->
val rawText = get(path)!!.getSequences().get(index) as RawText
// RawText.EMPTY_TEXT if content is null - deleted
if (rawText == RawText.EMPTY_TEXT) null else rawText.getContent()
})
val mergedFiles = resolveConflicts(mergeProvider, conflictsToVirtualFiles(conflicts), repository)
return mergeResult.result.toMutable().addChanged(mergedFiles)
}
private fun resolveConflicts(mergeProvider: JGitMergeProvider<out Any>, unresolvedFiles: MutableList<VirtualFile>, repository: Repository): List<String> {
val resolvedFiles: List<VirtualFile>
val mergedFiles = SmartList<String>()
while (true) {
resolvedFiles = resolveConflicts(unresolvedFiles, mergeProvider)
for (file in resolvedFiles) {
mergedFiles.add(file.getPath())
}
if (resolvedFiles.size() == unresolvedFiles.size()) {
break
}
else {
unresolvedFiles.removeAll(mergedFiles)
}
}
repository.commit()
return mergedFiles
}
+3 -2
View File
@@ -24,8 +24,9 @@ import org.jetbrains.settingsRepository.UpdateResult
class Reset(manager: GitRepositoryManager, indicator: ProgressIndicator) : Pull(manager, indicator) {
fun reset(toTheirs: Boolean, localRepositoryInitializer: (() -> Unit)? = null): UpdateResult {
val message = if (toTheirs) "Overwrite local to ${manager.getUpstream()}" else "Overwrite remote ${manager.getUpstream()} to local"
if (LOG.isDebugEnabled()) {
LOG.debug("Reset to ${if (toTheirs) "theirs" else "my"}")
LOG.debug(message)
}
val resetResult = repository.resetHard()
@@ -33,7 +34,7 @@ class Reset(manager: GitRepositoryManager, indicator: ProgressIndicator) : Pull(
indicator?.checkCanceled()
val commitMessage = commitMessageFormatter.message(if (toTheirs) "Overwrite local to ${manager.getUpstream()}" else "Overwrite remote ${manager.getUpstream()} to local")
val commitMessage = commitMessageFormatter.message(message)
// grab added/deleted/renamed/modified files
val mergeStrategy = if (toTheirs) MergeStrategy.THEIRS else MergeStrategy.OURS
val firstMergeResult = pull(mergeStrategy, commitMessage)
+7 -3
View File
@@ -59,7 +59,7 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
// well, we cannot commit? No problem, upcoming action must do something smart and solve the situation
}
catch (e: ProcessCanceledException) {
LOG.debug("Canceled")
LOG.warn("Canceled")
return
}
catch (e: Throwable) {
@@ -104,7 +104,7 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
return
}
catch (e: Throwable) {
if (e !is AuthenticationException && e !is NoRemoteRepositoryException) {
if (e !is AuthenticationException && e !is NoRemoteRepositoryException && e !is CannotResolveConflictInTestMode) {
LOG.error(e)
}
exception = e
@@ -188,4 +188,8 @@ enum class SyncType {
MERGE,
OVERWRITE_LOCAL,
OVERWRITE_REMOTE
}
}
class NoRemoteRepositoryException(cause: Throwable) : RuntimeException(cause.getMessage(), cause)
class CannotResolveConflictInTestMode() : RuntimeException()
+55 -8
View File
@@ -17,9 +17,12 @@ package org.jetbrains.settingsRepository.test
import com.intellij.mock.MockVirtualFileSystem
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.impl.stores.StreamProvider
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vcs.merge.MergeSession
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.path
import com.intellij.util.PathUtilRt
import org.assertj.core.api.Assertions.assertThat
import org.eclipse.jgit.api.Git
@@ -28,16 +31,24 @@ import org.jetbrains.jgit.dirCache.AddFile
import org.jetbrains.jgit.dirCache.deletePath
import org.jetbrains.jgit.dirCache.edit
import org.jetbrains.jgit.dirCache.writePath
import org.jetbrains.settingsRepository.AM
import org.jetbrains.settingsRepository.CannotResolveConflictInTestMode
import org.jetbrains.settingsRepository.SyncType
import org.jetbrains.settingsRepository.conflictResolver
import org.jetbrains.settingsRepository.git.GitRepositoryManager
import org.jetbrains.settingsRepository.git.commit
import org.jetbrains.settingsRepository.git.computeIndexDiff
import org.jetbrains.settingsRepository.git.resetHard
import org.junit.Test
import java.io.File
import java.util.Arrays
import kotlin.properties.Delegates
// kotlin bug, cannot be val (.NoSuchMethodError: org.jetbrains.settingsRepository.SettingsRepositoryPackage.getMARKER_ACCEPT_MY()[B)
object AM {
val MARKER_ACCEPT_MY: ByteArray = "__accept my__".toByteArray()
val MARKER_ACCEPT_THEIRS: ByteArray = "__accept theirs__".toByteArray()
}
class GitTest : TestCase() {
private val repositoryManager: GitRepositoryManager
get() = icsManager.repositoryManager as GitRepositoryManager
@@ -49,6 +60,28 @@ class GitTest : TestCase() {
tempDirManager.createRepository("upstream")
}
init {
conflictResolver = { files, mergeProvider ->
val mergeSession = mergeProvider.createMergeSession(files)
for (file in files) {
val mergeData = mergeProvider.loadRevisions(file)
if (Arrays.equals(mergeData.CURRENT, AM.MARKER_ACCEPT_MY) || Arrays.equals(mergeData.LAST, AM.MARKER_ACCEPT_THEIRS)) {
mergeSession.conflictResolvedForFile(file, MergeSession.Resolution.AcceptedYours)
}
else if (Arrays.equals(mergeData.CURRENT, AM.MARKER_ACCEPT_THEIRS) || Arrays.equals(mergeData.LAST, AM.MARKER_ACCEPT_MY)) {
mergeSession.conflictResolvedForFile(file, MergeSession.Resolution.AcceptedTheirs)
}
else if (Arrays.equals(mergeData.LAST, AM.MARKER_ACCEPT_MY)) {
file.setBinaryContent(mergeData.LAST!!)
mergeProvider.conflictResolvedForFile(file)
}
else {
throw CannotResolveConflictInTestMode()
}
}
}
}
private fun addAndCommit(path: String): FileInfo {
val data = FileUtil.loadFileBytes(File(testDataPath, PathUtilRt.getFileName(path)))
provider.save(path, data)
@@ -284,15 +317,24 @@ class GitTest : TestCase() {
Test fun `commit if unmerged`() {
createLocalRepository(null)
provider.saveContent("remote.xml", "<foo />")
try {
sync(SyncType.MERGE)
}
catch (e: CannotResolveConflictInTestMode) {
}
// repository in unmerged state
conflictResolver = {files, mergeProvider ->
assertThat(files).hasSize(1)
assertThat(files.first().path).isEqualTo("remote.xml")
val mergeSession = mergeProvider.createMergeSession(files)
mergeSession.conflictResolvedForFile(files.first(), MergeSession.Resolution.AcceptedTheirs)
}
sync(SyncType.MERGE)
provider.delete("remote.xml", RoamingType.PER_USER)
repositoryManager.commit()
sync(SyncType.MERGE)
restoreRemoteAfterPush()
compareFiles(fs())
compareFiles(fs("remote.xml"))
}
// remote is uninitialized (empty - initial commit is not done)
@@ -364,4 +406,9 @@ class GitTest : TestCase() {
private fun sync(syncType: SyncType) {
icsManager.sync(syncType, fixtureManager.projectFixture.getProject())
}
}
fun StreamProvider.saveContent(fileSpec: String, content: String) {
val data = content.toByteArray()
saveContent(fileSpec, data, data.size(), RoamingType.PER_USER)
}