Skip to content

Commit e4cf3fc

Browse files
committed
Fix validations fixes
1 parent 3db2326 commit e4cf3fc

File tree

5 files changed

+79
-45
lines changed

5 files changed

+79
-45
lines changed

artifactory/cli/ide/common.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ide
22

33
import (
44
"fmt"
5+
"strings"
56

67
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
78
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
@@ -28,3 +29,40 @@ func HasServerConfigFlags(c *components.Context) bool {
2829
// Only consider password if other required fields are also provided
2930
(c.IsFlagSet("password") && (c.IsFlagSet("url") || c.IsFlagSet("server-id")))
3031
}
32+
33+
// ExtractRepoKeyFromURL extracts the repository key from both JetBrains and VSCode extension URLs.
34+
// For JetBrains: https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins
35+
// For VSCode: https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery
36+
// Returns the repo key (e.g., "jetbrains-plugins" or "vscode-extensions")
37+
func ExtractRepoKeyFromURL(repoURL string) (string, error) {
38+
if repoURL == "" {
39+
return "", fmt.Errorf("URL is empty")
40+
}
41+
42+
url := strings.TrimSpace(repoURL)
43+
url = strings.TrimPrefix(url, "https://")
44+
url = strings.TrimPrefix(url, "http://")
45+
url = strings.TrimSuffix(url, "/")
46+
47+
// Check for JetBrains plugins API
48+
if idx := strings.Index(url, "/api/jetbrainsplugins/"); idx != -1 {
49+
rest := url[idx+len("/api/jetbrainsplugins/"):]
50+
parts := strings.SplitN(rest, "/", 2)
51+
if len(parts) == 0 || parts[0] == "" {
52+
return "", fmt.Errorf("repository key not found in JetBrains URL")
53+
}
54+
return parts[0], nil
55+
}
56+
57+
// Check for VSCode extensions API
58+
if idx := strings.Index(url, "/api/vscodeextensions/"); idx != -1 {
59+
rest := url[idx+len("/api/vscodeextensions/"):]
60+
parts := strings.SplitN(rest, "/", 2)
61+
if len(parts) == 0 || parts[0] == "" {
62+
return "", fmt.Errorf("repository key not found in VSCode URL")
63+
}
64+
return parts[0], nil
65+
}
66+
67+
return "", fmt.Errorf("URL does not contain a supported API type (/api/jetbrainsplugins/ or /api/vscodeextensions/)")
68+
}

artifactory/cli/ide/jetbrains/cli.go

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func getArguments() []components.Argument {
5858

5959
// Main command action: orchestrates argument parsing, server config, and command execution
6060
func jetbrainsConfigCmd(c *components.Context) error {
61-
repositoryURL, repoKey, err := getJetbrainsRepoKeyAndURL(c)
61+
repoKey, repositoryURL, err := getJetbrainsRepoKeyAndURL(c)
6262
if err != nil {
6363
return err
6464
}
@@ -69,6 +69,11 @@ func jetbrainsConfigCmd(c *components.Context) error {
6969
}
7070

7171
jetbrainsCmd := jetbrains.NewJetbrainsCommand(repositoryURL, repoKey)
72+
73+
// Determine if this is a direct URL (argument provided) vs constructed URL (server-id + repo-key)
74+
isDirectURL := c.GetNumberOfArgs() > 0 && isValidUrl(c.GetArgumentAt(0))
75+
jetbrainsCmd.SetDirectURL(isDirectURL)
76+
7277
if rtDetails != nil {
7378
jetbrainsCmd.SetServerDetails(rtDetails)
7479
}
@@ -80,7 +85,7 @@ func jetbrainsConfigCmd(c *components.Context) error {
8085
func getJetbrainsRepoKeyAndURL(c *components.Context) (repoKey, repositoryURL string, err error) {
8186
if c.GetNumberOfArgs() > 0 && isValidUrl(c.GetArgumentAt(0)) {
8287
repositoryURL = c.GetArgumentAt(0)
83-
repoKey, err = extractRepoKeyFromRepositoryURL(repositoryURL)
88+
repoKey, err = ide.ExtractRepoKeyFromURL(repositoryURL)
8489
if err != nil {
8590
return
8691
}
@@ -116,23 +121,6 @@ func getJetbrainsRepoKeyAndURL(c *components.Context) (repoKey, repositoryURL st
116121
return
117122
}
118123

119-
// extractRepoKeyFromRepositoryURL extracts the repo key from a JetBrains plugins repository URL.
120-
func extractRepoKeyFromRepositoryURL(repositoryURL string) (string, error) {
121-
if repositoryURL == "" {
122-
return "", fmt.Errorf("repository URL is empty")
123-
}
124-
trimmed := strings.TrimSuffix(repositoryURL, "/")
125-
parts := strings.Split(trimmed, "/api/jetbrainsplugins/")
126-
if len(parts) != 2 {
127-
return "", fmt.Errorf("repository URL does not contain /api/jetbrainsplugins/")
128-
}
129-
pathParts := strings.SplitN(parts[1], "/", 2)
130-
if len(pathParts) == 0 || pathParts[0] == "" {
131-
return "", fmt.Errorf("repository key not found in repository URL")
132-
}
133-
return pathParts[0], nil
134-
}
135-
136124
// getJetbrainsServerDetails returns server details for validation, or nil if not available
137125
func getJetbrainsServerDetails(c *components.Context) (*config.ServerDetails, error) {
138126
if ide.HasServerConfigFlags(c) {
@@ -148,7 +136,7 @@ func getJetbrainsServerDetails(c *components.Context) (*config.ServerDetails, er
148136
if err != nil {
149137
// If no default server, that's okay - we'll just skip validation
150138
log.Debug("No default server configuration found, skipping repository validation")
151-
return nil, nil
139+
return nil, nil //nolint:nilerr // Intentionally ignoring error to skip validation when no default server
152140
}
153141
return rtDetails, nil
154142
}

artifactory/cli/ide/vscode/cli.go

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ func vscodeConfigCmd(c *components.Context) error {
7373
}
7474

7575
vscodeCmd := vscode.NewVscodeCommand(repoKey, productPath, serviceURL)
76+
77+
// Determine if this is a direct URL (argument provided) vs constructed URL (server-id + repo-key)
78+
isDirectURL := c.GetNumberOfArgs() > 0 && isValidUrl(c.GetArgumentAt(0))
79+
vscodeCmd.SetDirectURL(isDirectURL)
80+
7681
if rtDetails != nil {
7782
vscodeCmd.SetServerDetails(rtDetails)
7883
}
@@ -84,12 +89,10 @@ func vscodeConfigCmd(c *components.Context) error {
8489
func getVscodeRepoKeyAndURL(c *components.Context) (repoKey, serviceURL string, err error) {
8590
if c.GetNumberOfArgs() > 0 && isValidUrl(c.GetArgumentAt(0)) {
8691
serviceURL = c.GetArgumentAt(0)
87-
repoKey, err = extractRepoKeyFromServiceURL(serviceURL)
92+
repoKey, err = ide.ExtractRepoKeyFromURL(serviceURL)
8893
if err != nil {
8994
return
9095
}
91-
log.Info("[DEBUG] Extracted repoKey:", repoKey)
92-
log.Info("[DEBUG] Service URL:", serviceURL)
9396
return
9497
}
9598

@@ -122,23 +125,6 @@ func getVscodeRepoKeyAndURL(c *components.Context) (repoKey, serviceURL string,
122125
return
123126
}
124127

125-
// extractRepoKeyFromServiceURL extracts the repo key from a VSCode extensions service URL.
126-
func extractRepoKeyFromServiceURL(serviceURL string) (string, error) {
127-
if serviceURL == "" {
128-
return "", fmt.Errorf("service URL is empty")
129-
}
130-
trimmed := strings.TrimSuffix(serviceURL, "/")
131-
parts := strings.Split(trimmed, "/api/vscodeextensions/")
132-
if len(parts) != 2 {
133-
return "", fmt.Errorf("service URL does not contain /api/vscodeextensions/")
134-
}
135-
pathParts := strings.SplitN(parts[1], "/", 2)
136-
if len(pathParts) == 0 || pathParts[0] == "" {
137-
return "", fmt.Errorf("repository key not found in service URL")
138-
}
139-
return pathParts[0], nil
140-
}
141-
142128
// getVscodeServerDetails returns server details for validation, or nil if not available
143129
func getVscodeServerDetails(c *components.Context) (*config.ServerDetails, error) {
144130
if ide.HasServerConfigFlags(c) {
@@ -154,7 +140,7 @@ func getVscodeServerDetails(c *components.Context) (*config.ServerDetails, error
154140
if err != nil {
155141
// If no default server, that's okay - we'll just skip validation
156142
log.Debug("No default server configuration found, skipping repository validation")
157-
return nil, nil
143+
return nil, nil //nolint:nilerr // Intentionally ignoring error to skip validation when no default server
158144
}
159145
return rtDetails, nil
160146
}

artifactory/commands/ide/jetbrains/jetbrains.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type JetbrainsCommand struct {
2424
backupPaths map[string]string
2525
serverDetails *config.ServerDetails
2626
repoKey string
27+
isDirectURL bool // true if URL was provided directly, false if constructed from server-id + repo-key
2728
}
2829

2930
// IDEInstallation represents a detected JetBrains IDE installation
@@ -57,6 +58,7 @@ func NewJetbrainsCommand(repositoryURL, repoKey string) *JetbrainsCommand {
5758
repositoryURL: repositoryURL,
5859
repoKey: repoKey,
5960
backupPaths: make(map[string]string),
61+
isDirectURL: false, // default to false, will be set explicitly
6062
}
6163
}
6264

@@ -73,15 +75,24 @@ func (jc *JetbrainsCommand) CommandName() string {
7375
return "rt_jetbrains_config"
7476
}
7577

78+
// SetDirectURL marks this command as using a direct URL (skip validation)
79+
func (jc *JetbrainsCommand) SetDirectURL(isDirect bool) *JetbrainsCommand {
80+
jc.isDirectURL = isDirect
81+
return jc
82+
}
83+
7684
// Run executes the JetBrains configuration command
7785
func (jc *JetbrainsCommand) Run() error {
7886
log.Info("Configuring JetBrains IDEs plugin repository...")
7987

80-
// Validate repository if we have server details and repo key
81-
if jc.serverDetails != nil && jc.repoKey != "" {
88+
// Only validate repository if we have server details and repo key AND it's not a direct URL
89+
// Skip validation when using direct repository URL since no server-id is involved
90+
if jc.serverDetails != nil && jc.repoKey != "" && !jc.isDirectURL {
8291
if err := jc.validateRepository(); err != nil {
8392
return errorutils.CheckError(fmt.Errorf("repository validation failed: %w", err))
8493
}
94+
} else if jc.isDirectURL {
95+
log.Debug("Direct repository URL provided, skipping repository validation")
8596
}
8697

8798
if err := jc.detectJetBrainsIDEs(); err != nil {

artifactory/commands/ide/vscode/vscode.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type VscodeCommand struct {
2525
backupPath string
2626
serverDetails *config.ServerDetails
2727
repoKey string
28+
isDirectURL bool // true if URL was provided directly, false if constructed from server-id + repo-key
2829
}
2930

3031
// NewVscodeCommand creates a new VSCode configuration command
@@ -33,6 +34,7 @@ func NewVscodeCommand(repoKey, productPath, serviceURL string) *VscodeCommand {
3334
repoKey: repoKey,
3435
productPath: productPath,
3536
serviceURL: serviceURL,
37+
isDirectURL: false, // default to false, will be set explicitly
3638
}
3739
}
3840

@@ -49,15 +51,24 @@ func (vc *VscodeCommand) CommandName() string {
4951
return "rt_vscode_config"
5052
}
5153

54+
// SetDirectURL marks this command as using a direct URL (skip validation)
55+
func (vc *VscodeCommand) SetDirectURL(isDirect bool) *VscodeCommand {
56+
vc.isDirectURL = isDirect
57+
return vc
58+
}
59+
5260
// Run executes the VSCode configuration command
5361
func (vc *VscodeCommand) Run() error {
5462
log.Info("Configuring VSCode extensions repository...")
5563

56-
// Validate repository if we have server details and repo key
57-
if vc.serverDetails != nil && vc.repoKey != "" {
64+
// Only validate repository if we have server details and repo key AND it's not a direct URL
65+
// Skip validation when using direct service URL since no server-id is involved
66+
if vc.serverDetails != nil && vc.repoKey != "" && !vc.isDirectURL {
5867
if err := vc.validateRepository(); err != nil {
5968
return errorutils.CheckError(fmt.Errorf("repository validation failed: %w", err))
6069
}
70+
} else if vc.isDirectURL {
71+
log.Debug("Direct service URL provided, skipping repository validation")
6172
}
6273

6374
if vc.productPath == "" {

0 commit comments

Comments
 (0)