<commit_before>/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See http://swift.org/LICENSE.txt for license information
 See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Basic
import Build
import PackageModel
import PackageLoading
import PackageGraph
import SourceControl
import Utility
import Xcodeproj
import Workspace

struct FetchDeprecatedDiagnostic: DiagnosticData {
    static let id = DiagnosticID(
        type: AnyDiagnostic.self,
        name: "org.swift.diags.fetch-deprecated",
        defaultBehavior: .warning,
        description: {
            $0 <<< "'fetch' command is deprecated; use 'resolve' instead"
        }
    )
}

/// swift-package tool namespace
public class SwiftPackageTool: SwiftTool<PackageToolOptions> {

   public convenience init(args: [String]) {
       self.init(
            toolName: "package",
            usage: "[options] subcommand",
            overview: "Perform operations on Swift packages",
            args: args,
            seeAlso: type(of: self).otherToolNames()
        )
    }
    override func runImpl() throws {
        switch options.mode {
        case .version:
            print(Versioning.currentVersion.completeDisplayString)

        case .initPackage:
            let initPackage = try InitPackage(destinationPath: localFileSystem.currentWorkingDirectory!, packageType: options.initMode)
            initPackage.progressReporter = { message in
                print(message)
            }
            try initPackage.writePackageStructure()

        case .clean:
            try getActiveWorkspace().clean(with: diagnostics)

        case .reset:
            try getActiveWorkspace().reset(with: diagnostics)

        case .update:
            let workspace = try getActiveWorkspace()
            try workspace.updateDependencies(
                root: getWorkspaceRoot(),
                diagnostics: diagnostics
            )

        case .fetch:
            diagnostics.emit(data: FetchDeprecatedDiagnostic())
            try resolve()

        case .resolve:
            let resolveOptions = options.resolveOptions

            // If a package is provided, use that to resolve the dependencies.
            if let packageName = resolveOptions.packageName {
                let workspace = try getActiveWorkspace()
                return try workspace.resolve(
                    packageName: packageName,
                    root: getWorkspaceRoot(),
                    version: resolveOptions.version.flatMap(Version.init(string:)),
                    branch: resolveOptions.branch,
                    revision: resolveOptions.revision,
                    diagnostics: diagnostics)
            }

            // Otherwise, run a normal resolve.
            try resolve()

        case .edit:
            let packageName = options.editOptions.packageName!
            try resolve()
            let workspace = try getActiveWorkspace()

            // Create revision object if provided by user.
            let revision = options.editOptions.revision.flatMap({ Revision(identifier: $0) })

            // Put the dependency in edit mode.
            workspace.edit(
                packageName: packageName,
                path: options.editOptions.path,
                revision: revision,
                checkoutBranch: options.editOptions.checkoutBranch,
                diagnostics: diagnostics)

        case .unedit:
            let packageName = options.editOptions.packageName!
            try resolve()
            let workspace = try getActiveWorkspace()

            try workspace.unedit(
                packageName: packageName,
                forceRemove: options.editOptions.shouldForceRemove,
                root: getWorkspaceRoot(),
                diagnostics: diagnostics
            )

        case .showDependencies:
            let graph = try loadPackageGraph()
            dumpDependenciesOf(rootPackage: graph.rootPackages[0], mode: options.showDepsMode)

        case .toolsVersion:
            let pkg = try getPackageRoot()

            switch options.toolsVersionMode {
            case .display:
                let toolsVersionLoader = ToolsVersionLoader()
                let version = try toolsVersionLoader.load(at: pkg, fileSystem: localFileSystem)
                print("\(version)")

            case .set(let value):
                guard let toolsVersion = ToolsVersion(string: value) else {
                    // FIXME: Probably lift this error defination to ToolsVersion.
                    throw ToolsVersionLoader.Error.malformed(specifier: value, file: pkg)
                }
                try writeToolsVersion(at: pkg, version: toolsVersion, fs: &localFileSystem)

            case .setCurrent:
                // Write the tools version with current version but with patch set to zero.
                // We do this to avoid adding unnecessary constraints to patch versions, if
                // the package really needs it, they can do it using --set option.
                try writeToolsVersion(
                    at: pkg, version: ToolsVersion.currentToolsVersion.zeroedPatch, fs: &localFileSystem)
            }

        case .generateXcodeproj:
            let graph = try loadPackageGraph()

            let projectName: String
            let dstdir: AbsolutePath

            switch options.outputPath {
            case let outpath? where outpath.suffix == ".xcodeproj":
                // if user specified path ending with .xcodeproj, use that
                projectName = String(outpath.basename.dropLast(10))
                dstdir = outpath.parentDirectory
            case let outpath?:
                dstdir = outpath
                projectName = graph.rootPackages[0].name
            case _:
                dstdir = try getPackageRoot()
                projectName = graph.rootPackages[0].name
            }
            let xcodeprojPath = Xcodeproj.buildXcodeprojPath(outputDir: dstdir, projectName: projectName)
            try Xcodeproj.generate(
                projectName: projectName,
                xcodeprojPath: xcodeprojPath,
                graph: graph,
                options: options.xcodeprojOptions,
                diagnostics: diagnostics)

            print("generated:", xcodeprojPath.prettyPath(cwd: originalWorkingDirectory))

            // Run the file watcher if requested.
            if options.xcodeprojOptions.enableAutogeneration {
                try WatchmanHelper(
                    diagnostics: diagnostics,
                    watchmanScriptsDir: buildPath.appending(component: "watchman"),
                    packageRoot: packageRoot!
                ).runXcodeprojWatcher(options.xcodeprojOptions)
            }

        case .describe:
            let graph = try loadPackageGraph()
            describe(graph.rootPackages[0].underlyingPackage, in: options.describeMode, on: stdoutStream)

        case .dumpPackage:
            let graph = try loadPackageGraph()
            let manifest = graph.rootPackages[0].manifest
            print(try manifest.jsonString())

        case .completionTool:
            switch options.completionToolMode {
            case .generateBashScript?:
                bash_template(on: stdoutStream)
            case .generateZshScript?:
                zsh_template(on: stdoutStream)
            case .listDependencies?:
                let graph = try loadPackageGraph()
                dumpDependenciesOf(rootPackage: graph.rootPackages[0], mode: .flatlist)
            case .listExecutables?:
                let graph = try loadPackageGraph()
                let package = graph.rootPackages[0].underlyingPackage
                let executables = package.targets.filter { $0.type == .executable }
                for executable in executables {
                    stdoutStream <<< "\(executable.name)\n"
                }
                stdoutStream.flush()<commit_msg>SR-6277 "WIP" Mute non-JSON output from "dump-package" (#1599)<commit_after>/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See http://swift.org/LICENSE.txt for license information
 See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Basic
import Build
import PackageModel
import PackageLoading
import PackageGraph
import SourceControl
import Utility
import Xcodeproj
import Workspace

struct FetchDeprecatedDiagnostic: DiagnosticData {
    static let id = DiagnosticID(
        type: AnyDiagnostic.self,
        name: "org.swift.diags.fetch-deprecated",
        defaultBehavior: .warning,
        description: {
            $0 <<< "'fetch' command is deprecated; use 'resolve' instead"
        }
    )
}

/// swift-package tool namespace
public class SwiftPackageTool: SwiftTool<PackageToolOptions> {

   public convenience init(args: [String]) {
       self.init(
            toolName: "package",
            usage: "[options] subcommand",
            overview: "Perform operations on Swift packages",
            args: args,
            seeAlso: type(of: self).otherToolNames()
        )
    }
    override func runImpl() throws {
        switch options.mode {
        case .version:
            print(Versioning.currentVersion.completeDisplayString)

        case .initPackage:
            let initPackage = try InitPackage(destinationPath: localFileSystem.currentWorkingDirectory!, packageType: options.initMode)
            initPackage.progressReporter = { message in
                print(message)
            }
            try initPackage.writePackageStructure()

        case .clean:
            try getActiveWorkspace().clean(with: diagnostics)

        case .reset:
            try getActiveWorkspace().reset(with: diagnostics)

        case .update:
            let workspace = try getActiveWorkspace()
            try workspace.updateDependencies(
                root: getWorkspaceRoot(),
                diagnostics: diagnostics
            )

        case .fetch:
            diagnostics.emit(data: FetchDeprecatedDiagnostic())
            try resolve()

        case .resolve:
            let resolveOptions = options.resolveOptions

            // If a package is provided, use that to resolve the dependencies.
            if let packageName = resolveOptions.packageName {
                let workspace = try getActiveWorkspace()
                return try workspace.resolve(
                    packageName: packageName,
                    root: getWorkspaceRoot(),
                    version: resolveOptions.version.flatMap(Version.init(string:)),
                    branch: resolveOptions.branch,
                    revision: resolveOptions.revision,
                    diagnostics: diagnostics)
            }

            // Otherwise, run a normal resolve.
            try resolve()

        case .edit:
            let packageName = options.editOptions.packageName!
            try resolve()
            let workspace = try getActiveWorkspace()

            // Create revision object if provided by user.
            let revision = options.editOptions.revision.flatMap({ Revision(identifier: $0) })

            // Put the dependency in edit mode.
            workspace.edit(
                packageName: packageName,
                path: options.editOptions.path,
                revision: revision,
                checkoutBranch: options.editOptions.checkoutBranch,
                diagnostics: diagnostics)

        case .unedit:
            let packageName = options.editOptions.packageName!
            try resolve()
            let workspace = try getActiveWorkspace()

            try workspace.unedit(
                packageName: packageName,
                forceRemove: options.editOptions.shouldForceRemove,
                root: getWorkspaceRoot(),
                diagnostics: diagnostics
            )

        case .showDependencies:
            let graph = try loadPackageGraph()
            dumpDependenciesOf(rootPackage: graph.rootPackages[0], mode: options.showDepsMode)

        case .toolsVersion:
            let pkg = try getPackageRoot()

            switch options.toolsVersionMode {
            case .display:
                let toolsVersionLoader = ToolsVersionLoader()
                let version = try toolsVersionLoader.load(at: pkg, fileSystem: localFileSystem)
                print("\(version)")

            case .set(let value):
                guard let toolsVersion = ToolsVersion(string: value) else {
                    // FIXME: Probably lift this error defination to ToolsVersion.
                    throw ToolsVersionLoader.Error.malformed(specifier: value, file: pkg)
                }
                try writeToolsVersion(at: pkg, version: toolsVersion, fs: &localFileSystem)

            case .setCurrent:
                // Write the tools version with current version but with patch set to zero.
                // We do this to avoid adding unnecessary constraints to patch versions, if
                // the package really needs it, they can do it using --set option.
                try writeToolsVersion(
                    at: pkg, version: ToolsVersion.currentToolsVersion.zeroedPatch, fs: &localFileSystem)
            }

        case .generateXcodeproj:
            let graph = try loadPackageGraph()

            let projectName: String
            let dstdir: AbsolutePath

            switch options.outputPath {
            case let outpath? where outpath.suffix == ".xcodeproj":
                // if user specified path ending with .xcodeproj, use that
                projectName = String(outpath.basename.dropLast(10))
                dstdir = outpath.parentDirectory
            case let outpath?:
                dstdir = outpath
                projectName = graph.rootPackages[0].name
            case _:
                dstdir = try getPackageRoot()
                projectName = graph.rootPackages[0].name
            }
            let xcodeprojPath = Xcodeproj.buildXcodeprojPath(outputDir: dstdir, projectName: projectName)
            try Xcodeproj.generate(
                projectName: projectName,
                xcodeprojPath: xcodeprojPath,
                graph: graph,
                options: options.xcodeprojOptions,
                diagnostics: diagnostics)

            print("generated:", xcodeprojPath.prettyPath(cwd: originalWorkingDirectory))

            // Run the file watcher if requested.
            if options.xcodeprojOptions.enableAutogeneration {
                try WatchmanHelper(
                    diagnostics: diagnostics,
                    watchmanScriptsDir: buildPath.appending(component: "watchman"),
                    packageRoot: packageRoot!
                ).runXcodeprojWatcher(options.xcodeprojOptions)
            }

        case .describe:
            let graph = try loadPackageGraph()
            describe(graph.rootPackages[0].underlyingPackage, in: options.describeMode, on: stdoutStream)

        case .dumpPackage:
            let workspace = try getActiveWorkspace()
            let root = try getWorkspaceRoot()
            let manifests = workspace.loadRootManifests(packages: root.packages, diagnostics: diagnostics)
            print(try manifests[0].jsonString())

        case .completionTool:
            switch options.completionToolMode {
            case .generateBashScript?:
                bash_template(on: stdoutStream)
            case .generateZshScript?:
                zsh_template(on: stdoutStream)
            case .listDependencies?:
                let graph = try loadPackageGraph()
                dumpDependenciesOf(rootPackage: graph.rootPackages[0], mode: .flatlist)
            case .listExecutables?:
                let graph = try loadPackageGraph()
                let package = graph.rootPackages[0].underlyingPackage
                let executables = package.targets.filter { $0.type == .executable }
                for executable in executables {
                    stdoutStream <<< "\(executable.name)\n"
                }
                stdoutStream.flush()
{'fraction_non_alphanumeric': 0.072346676459787, 'fraction_numerical': 0.0031827641082139797, 'mean_word_length': 1.8489973844812555, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5549437', 'n_tokens_mistral': 3983, 'n_tokens_neox': 3737, 'n_words': 1067}