internal/cmd/init.go (118 lines of code) (raw):
/*
* Copyright 2021-2024 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
*
* https://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 cmd
import (
"fmt"
"path/filepath"
"github.com/JetBrains/qodana-cli/internal/platform/commoncontext"
"github.com/JetBrains/qodana-cli/internal/platform/msg"
"github.com/JetBrains/qodana-cli/internal/platform/product"
"github.com/JetBrains/qodana-cli/internal/platform/qdenv"
"github.com/JetBrains/qodana-cli/internal/platform/qdyaml"
"github.com/JetBrains/qodana-cli/internal/platform/tokenloader"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// newInitCommand returns a new instance of the show command.
func newInitCommand() *cobra.Command {
cliOptions := &initOptions{}
cmd := &cobra.Command{
Use: "init",
Short: "Configure a project for Qodana",
Long: `Configure a project for Qodana: prepare Qodana configuration file by analyzing the project structure and generating a default configuration qodana.yaml file.`,
Run: func(cmd *cobra.Command, args []string) {
qdenv.InitializeQodanaGlobalEnv(qdenv.EmptyEnvProvider())
localQodanaYamlFullPath := qdyaml.GetLocalNotEffectiveQodanaYamlFullPath(
cliOptions.ProjectDir,
cliOptions.ConfigName,
)
if localQodanaYamlFullPath == "" {
localQodanaYamlFullPath = filepath.Join(cliOptions.ProjectDir, "qodana.yaml")
}
qodanaYaml := qdyaml.LoadQodanaYamlByFullPath(localQodanaYamlFullPath)
ide := qodanaYaml.Ide
linter := qodanaYaml.Linter
if (linter == "" && ide == "") || cliOptions.Force {
absPath, err := filepath.Abs(cliOptions.ProjectDir)
if err != nil {
log.Fatal(err)
}
cliOptions.ProjectDir = absPath
if msg.IsInteractive() && !msg.AskUserConfirm(
fmt.Sprintf(
"Do you want to set up Qodana in %s",
msg.PrimaryBold(cliOptions.ProjectDir),
),
) {
return
}
token := qdenv.GetQodanaGlobalEnv(qdenv.QodanaToken)
analyzer := commoncontext.SelectAnalyzerForPath(cliOptions.ProjectDir, token)
writeQodanaLinterToYamlFileWithWarning(
localQodanaYamlFullPath,
analyzer,
)
checkToken(analyzer, cliOptions)
} else {
msg.EmptyMessage()
var analyzer string
if ide != "" {
analyzer = ide
} else if linter != "" {
analyzer = linter
}
msg.SuccessMessage(
"The product to use was already configured before: %s. Run the command with %s flag to re-init the project",
msg.PrimaryBold(analyzer),
msg.PrimaryBold("-f"),
)
}
if msg.IsInteractive() && qodanaYaml.IsDotNet() && (qodanaYaml.DotNet.IsEmpty() || cliOptions.Force) {
if commoncontext.GetAndSaveDotNetConfig(cliOptions.ProjectDir, localQodanaYamlFullPath) {
msg.SuccessMessage("The .NET configuration was successfully set")
}
}
msg.PrintFile(localQodanaYamlFullPath)
},
}
flags := cmd.Flags()
flags.StringVarP(&cliOptions.ProjectDir, "project-dir", "i", ".", "Root directory of the project to configure")
flags.BoolVarP(
&cliOptions.Force,
"force",
"f",
false,
"Force initialization (overwrite existing valid qodana.yaml)",
)
flags.StringVar(
&cliOptions.ConfigName,
"config",
"",
"Set a custom configuration file instead of 'qodana.yaml'. Relative paths in the configuration will be based on the project directory.",
)
return cmd
}
func checkToken(analyser product.Analyzer, cliOptions *initOptions) {
commonCtx := commoncontext.Context{
Analyzer: analyser,
ProjectDir: cliOptions.ProjectDir,
QodanaToken: qdenv.GetQodanaGlobalEnv(qdenv.QodanaToken),
}
if tokenloader.IsCloudTokenRequired(commonCtx) {
tokenloader.ValidateCloudToken(commonCtx, cliOptions.Force)
}
}
// WriteQodanaLinterToYamlFile adds the linter to the qodana.yaml file, also adds warning about sensetive information
func writeQodanaLinterToYamlFileWithWarning(qodanaYamlFullPath string, analyser product.Analyzer) {
q := qdyaml.LoadQodanaYamlByFullPath(qodanaYamlFullPath)
if q.Version == "" {
q.Version = "1.0"
}
q.Sort()
q = analyser.InitYaml(q)
err := q.WriteConfigWithWarning(qodanaYamlFullPath)
if err != nil {
log.Fatalf("writeConfig: %v", err)
}
}
type initOptions struct {
ProjectDir string
ConfigName string
Force bool
}