fun doOneStepSwitch()

in bunch-cli/src/main/kotlin/org/jetbrains/bunches/switch.kt [236:338]


fun doOneStepSwitch(suffixes: List<String>, repoPath: String, commitTitle: String) {
    val originBranchExtension = suffixes.first()
    val donorExtensionsPrioritized = suffixes.subList(1, suffixes.size).reversed().toSet()

    val root = File(repoPath)

    if (!isGitRoot(root)) {
        exitWithError(NO_GIT_EXCEPTION_TEXT)
    }

    val gitIgnoreParseResult = parseGitIgnore(root)

    val changedFiles = HashSet<FileChange>()

    val filesWithDonorExtensions = getFilesWithExtensions(root, gitIgnoreParseResult, donorExtensionsPrioritized)

    val affectedOriginFiles: Set<File> =
        filesWithDonorExtensions.mapTo(HashSet()) { child -> File(child.parentFile, child.nameWithoutExtension) }

    for (originFile in affectedOriginFiles) {
        val originFileModificationType: ChangeType

        val baseCopiedFile = originFile.toBunchFile(originBranchExtension)
        if (baseCopiedFile.exists()) {
            exitWithError("$SAVED_VALUE_EXISTS $baseCopiedFile")
        }

        if (originFile.exists()) {
            if (originFile.isDirectory) {
                exitWithError("$NO_DIRECTORIES_SUPPORT $originFile")
            }

            originFile.copyTo(baseCopiedFile)
            changedFiles.add(
                FileChange(
                    ChangeType.ADD,
                    baseCopiedFile
                )
            )

            originFile.delete()
            originFileModificationType = ChangeType.MODIFY
        } else {
            // File was absent and going to be introduced.
            // Create empty bunch files to show it's going to be removed in old branch.
            baseCopiedFile.createNewFile()
            changedFiles.add(
                FileChange(
                    ChangeType.ADD,
                    baseCopiedFile
                )
            )

            originFileModificationType = ChangeType.ADD
        }

        val targetFile = donorExtensionsPrioritized
            .asSequence()
            .map { extension ->
                originFile.toBunchFile(extension) }
            .first {
                it.exists()
            }

        if (targetFile.isDirectory) {
            exitWithError("Patch specific directories are not supported: $targetFile")
        }

        val isTargetRemoved = targetFile.readText().trim().isEmpty()
        if (!isTargetRemoved) {
            targetFile.copyTo(originFile)
            changedFiles.add(FileChange(originFileModificationType, originFile))
        } else {
            when (originFileModificationType) {
                ChangeType.ADD -> {
                    // Original file was copied, but there's nothing to add instead. Do nothing.
                }
                ChangeType.MODIFY -> {
                    changedFiles.add(
                        FileChange(
                            ChangeType.REMOVE,
                            originFile
                        )
                    )
                }
                ChangeType.REMOVE -> {
                    throw IllegalStateException("REMOVE state isn't expected for original file modification")
                }
            }
        }
    }

    if (changedFiles.isEmpty()) {
        exitWithError("No bunch files for switch found")
    }

    commitChanges(
        repoPath,
        changedFiles,
        commitTitle.replace("{target}", suffixes.last()),
        noVerify = true
    )
}