Skip to content

Commit f12ae1e

Browse files
Copilotsawka
andauthored
Add RenameLocalApp function to waveappstore (#2536)
## Plan: Add RenameLocalApp function to waveappstore - [x] Analyze existing code patterns in waveappstore.go - [x] Implement RenameLocalApp(appName string, newAppName string) error function - Validate newAppName using existing validation - Check if local/[appname] exists and rename to local/[newAppName] if it does - Check if draft/[appname] exists and rename to draft/[newAppName] if it does - Handle errors appropriately including rollback on partial failure - [x] Add documentation comments - [x] Run security checks (CodeQL - no issues found) ## Summary Successfully implemented `RenameLocalApp(appName string, newAppName string) error` function that: - Renames local apps in both `local/` and `draft/` namespaces - Validates app names and checks for conflicts - Implements proper error handling with rollback on partial failure - Passes all security checks with zero vulnerabilities Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
1 parent 8c50f7b commit f12ae1e

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

pkg/waveappstore/waveappstore.go

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ func ListAllEditableApps() ([]string, error) {
498498
return appIds, nil
499499
}
500500

501-
502501
func DraftHasLocalVersion(draftAppId string) (bool, error) {
503502
if err := ValidateAppId(draftAppId); err != nil {
504503
return false, fmt.Errorf("invalid appId: %w", err)
@@ -521,3 +520,84 @@ func DraftHasLocalVersion(draftAppId string) (bool, error) {
521520

522521
return true, nil
523522
}
523+
524+
// RenameLocalApp renames a local app by renaming its directories in both the local and draft namespaces.
525+
// It takes the current app name and the new app name (without namespace prefixes).
526+
// Both local/[appName] and draft/[appName] will be renamed if they exist.
527+
// Returns an error if the app doesn't exist in either namespace, if the new name is invalid,
528+
// or if the new name conflicts with an existing app.
529+
func RenameLocalApp(appName string, newAppName string) error {
530+
// Validate the old app name by constructing a valid appId
531+
oldLocalAppId := MakeAppId(AppNSLocal, appName)
532+
if err := ValidateAppId(oldLocalAppId); err != nil {
533+
return fmt.Errorf("invalid app name: %w", err)
534+
}
535+
536+
// Validate the new app name by constructing a valid appId
537+
newLocalAppId := MakeAppId(AppNSLocal, newAppName)
538+
if err := ValidateAppId(newLocalAppId); err != nil {
539+
return fmt.Errorf("invalid new app name: %w", err)
540+
}
541+
542+
homeDir := wavebase.GetHomeDir()
543+
waveappsDir := filepath.Join(homeDir, "waveapps")
544+
545+
oldLocalDir := filepath.Join(waveappsDir, AppNSLocal, appName)
546+
newLocalDir := filepath.Join(waveappsDir, AppNSLocal, newAppName)
547+
oldDraftDir := filepath.Join(waveappsDir, AppNSDraft, appName)
548+
newDraftDir := filepath.Join(waveappsDir, AppNSDraft, newAppName)
549+
550+
// Check if at least one of the apps exists
551+
localExists := false
552+
draftExists := false
553+
if _, err := os.Stat(oldLocalDir); err == nil {
554+
localExists = true
555+
} else if !os.IsNotExist(err) {
556+
return fmt.Errorf("failed to check local app: %w", err)
557+
}
558+
559+
if _, err := os.Stat(oldDraftDir); err == nil {
560+
draftExists = true
561+
} else if !os.IsNotExist(err) {
562+
return fmt.Errorf("failed to check draft app: %w", err)
563+
}
564+
565+
if !localExists && !draftExists {
566+
return fmt.Errorf("app '%s' does not exist in local or draft namespace", appName)
567+
}
568+
569+
// Check if new app name already exists in either namespace
570+
if _, err := os.Stat(newLocalDir); err == nil {
571+
return fmt.Errorf("local app '%s' already exists", newAppName)
572+
} else if !os.IsNotExist(err) {
573+
return fmt.Errorf("failed to check if new local app exists: %w", err)
574+
}
575+
576+
if _, err := os.Stat(newDraftDir); err == nil {
577+
return fmt.Errorf("draft app '%s' already exists", newAppName)
578+
} else if !os.IsNotExist(err) {
579+
return fmt.Errorf("failed to check if new draft app exists: %w", err)
580+
}
581+
582+
// Rename local app if it exists
583+
if localExists {
584+
if err := os.Rename(oldLocalDir, newLocalDir); err != nil {
585+
return fmt.Errorf("failed to rename local app: %w", err)
586+
}
587+
}
588+
589+
// Rename draft app if it exists
590+
if draftExists {
591+
if err := os.Rename(oldDraftDir, newDraftDir); err != nil {
592+
// If local was renamed but draft fails, try to rollback local rename
593+
if localExists {
594+
if rollbackErr := os.Rename(newLocalDir, oldLocalDir); rollbackErr != nil {
595+
return fmt.Errorf("failed to rename draft app (and failed to rollback local rename: %v): %w", rollbackErr, err)
596+
}
597+
}
598+
return fmt.Errorf("failed to rename draft app: %w", err)
599+
}
600+
}
601+
602+
return nil
603+
}

0 commit comments

Comments
 (0)