From 89d64cb1173c276a81739f1e73cb5a1396e7decc Mon Sep 17 00:00:00 2001 From: zyj Date: Wed, 4 Mar 2026 10:14:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9git=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- cmd/devpack/commands/capture.go | 59 ++++++++++++++++++ cmd/devpack/commands/diff.go | 45 ++++++++++++++ cmd/devpack/commands/export.go | 58 ++++++++++++++++++ cmd/devpack/commands/init.go | 39 ++++++++++++ cmd/devpack/commands/list.go | 51 ++++++++++++++++ cmd/devpack/commands/profile.go | 102 ++++++++++++++++++++++++++++++++ cmd/devpack/commands/restore.go | 60 +++++++++++++++++++ cmd/devpack/commands/root.go | 80 +++++++++++++++++++++++++ cmd/devpack/commands/scan.go | 44 ++++++++++++++ cmd/devpack/commands/version.go | 18 ++++++ cmd/devpack/main.go | 13 ++++ 12 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 cmd/devpack/commands/capture.go create mode 100644 cmd/devpack/commands/diff.go create mode 100644 cmd/devpack/commands/export.go create mode 100644 cmd/devpack/commands/init.go create mode 100644 cmd/devpack/commands/list.go create mode 100644 cmd/devpack/commands/profile.go create mode 100644 cmd/devpack/commands/restore.go create mode 100644 cmd/devpack/commands/root.go create mode 100644 cmd/devpack/commands/scan.go create mode 100644 cmd/devpack/commands/version.go create mode 100644 cmd/devpack/main.go diff --git a/.gitignore b/.gitignore index 9b0aa3b..714b297 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Binaries -devpack +# devpack devpack.exe *.exe *.dll diff --git a/cmd/devpack/commands/capture.go b/cmd/devpack/commands/capture.go new file mode 100644 index 0000000..ca9d859 --- /dev/null +++ b/cmd/devpack/commands/capture.go @@ -0,0 +1,59 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newCaptureCmd() *cobra.Command { + var ( + name string + description string + profile string + collectors string + filter string + all bool + encrypt bool + exclude string + tag string + yes bool + ) + + cmd := &cobra.Command{ + Use: "capture", + Short: "捕获环境并生成 Pack", + Long: `捕获当前开发环境的配置和工具信息,生成一个 Pack。`, + RunE: func(cmd *cobra.Command, args []string) error { + if name == "" { + return fmt.Errorf("必须指定 Pack 名称 (--name)") + } + fmt.Printf("📦 Capturing environment \"%s\"...\n", name) + // TODO: Implement capture logic + // 1. Load profile + // 2. Run collectors + // 3. Write data to temp directory + // 4. Generate manifest + // 5. Encrypt sensitive data (if enabled) + // 6. Create pack + fmt.Printf("✅ Pack created: %s\n", name) + fmt.Printf("\nRun 'devpack export %s -o %s.devpack' to export.\n", name, name) + return nil + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Pack 名称(必需)") + cmd.Flags().StringVarP(&description, "description", "d", "", "Pack 描述") + cmd.Flags().StringVarP(&profile, "profile", "p", "", "使用指定 Profile") + cmd.Flags().StringVarP(&collectors, "collectors", "c", "", "指定采集器(逗号分隔)") + cmd.Flags().StringVar(&filter, "filter", "", "过滤表达式") + cmd.Flags().BoolVar(&all, "all", false, "捕获所有可用采集器") + cmd.Flags().BoolVar(&encrypt, "encrypt", false, "加密敏感数据") + cmd.Flags().StringVar(&exclude, "exclude", "", "排除模式(逗号分隔)") + cmd.Flags().StringVar(&tag, "tag", "", "标签(逗号分隔)") + cmd.Flags().BoolVarP(&yes, "yes", "y", false, "跳过确认提示") + + _ = cmd.MarkFlagRequired("name") + + return cmd +} diff --git a/cmd/devpack/commands/diff.go b/cmd/devpack/commands/diff.go new file mode 100644 index 0000000..2a4d783 --- /dev/null +++ b/cmd/devpack/commands/diff.go @@ -0,0 +1,45 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newDiffCmd() *cobra.Command { + var ( + current bool + with string + collectors string + output string + ) + + cmd := &cobra.Command{ + Use: "diff ", + Short: "对比环境差异", + Long: `对比两个环境之间的差异。`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + packName := args[0] + + if current { + fmt.Printf("🔍 Comparing \"%s\" with current environment...\n\n", packName) + } else if with != "" { + fmt.Printf("🔍 Comparing \"%s\" with \"%s\"...\n\n", packName, with) + } else { + return fmt.Errorf("请指定对比目标: --current 或 --with ") + } + + // TODO: Implement diff logic + fmt.Println("(diff not yet implemented)") + return nil + }, + } + + cmd.Flags().BoolVar(¤t, "current", false, "与当前环境对比") + cmd.Flags().StringVar(&with, "with", "", "与另一个 Pack 对比") + cmd.Flags().StringVarP(&collectors, "collectors", "c", "", "只对比指定采集器") + cmd.Flags().StringVarP(&output, "output", "o", "table", "输出格式 (table|json|yaml)") + + return cmd +} diff --git a/cmd/devpack/commands/export.go b/cmd/devpack/commands/export.go new file mode 100644 index 0000000..691ba1f --- /dev/null +++ b/cmd/devpack/commands/export.go @@ -0,0 +1,58 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newExportCmd() *cobra.Command { + var output string + + cmd := &cobra.Command{ + Use: "export ", + Short: "导出 Pack 为文件", + Long: `将 Pack 导出为可移植的 .devpack 文件。`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + packName := args[0] + if output == "" { + output = packName + ".devpack" + } + fmt.Printf("📤 Exporting \"%s\" to %s...\n", packName, output) + // TODO: Implement export logic + fmt.Printf("✅ Exported: %s\n", output) + return nil + }, + } + + cmd.Flags().StringVarP(&output, "output", "o", "", "输出文件路径") + + return cmd +} + +func newImportCmd() *cobra.Command { + var ( + name string + verify bool + ) + + cmd := &cobra.Command{ + Use: "import ", + Short: "导入 Pack 文件", + Long: `导入 .devpack 文件到本地 Pack 存储。`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + filePath := args[0] + fmt.Printf("📥 Importing %s...\n", filePath) + // TODO: Implement import logic + fmt.Println("✅ Import complete!") + return nil + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "导入后的名称") + cmd.Flags().BoolVar(&verify, "verify", false, "导入前验证文件完整性") + + return cmd +} diff --git a/cmd/devpack/commands/init.go b/cmd/devpack/commands/init.go new file mode 100644 index 0000000..ff20123 --- /dev/null +++ b/cmd/devpack/commands/init.go @@ -0,0 +1,39 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newInitCmd() *cobra.Command { + var ( + profile string + template string + force bool + ) + + cmd := &cobra.Command{ + Use: "init", + Short: "初始化 DevPack 配置", + Long: `初始化 DevPack,创建配置目录和默认配置文件。`, + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println("🚀 Initializing DevPack...") + // TODO: Implement init logic + // 1. Create ~/.devpack/ directory + // 2. Create config.yaml + // 3. Create profiles/ directory + // 4. Create packs/ directory + // 5. Create logs/ directory + fmt.Println("✅ DevPack initialized successfully!") + fmt.Println("\nRun 'devpack scan' to scan your current environment.") + return nil + }, + } + + cmd.Flags().StringVarP(&profile, "profile", "p", "", "创建并使用指定名称的 Profile") + cmd.Flags().StringVarP(&template, "template", "t", "standard", "使用预设模板 (minimal|standard|full)") + cmd.Flags().BoolVar(&force, "force", false, "覆盖已有配置") + + return cmd +} diff --git a/cmd/devpack/commands/list.go b/cmd/devpack/commands/list.go new file mode 100644 index 0000000..476f835 --- /dev/null +++ b/cmd/devpack/commands/list.go @@ -0,0 +1,51 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newListCmd() *cobra.Command { + var ( + output string + detailed bool + ) + + cmd := &cobra.Command{ + Use: "list [packs|profiles|collectors]", + Short: "列出 Pack、Profile 或采集器", + Long: `列出本地存储的 Pack、配置的 Profile 或所有可用的采集器。`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + subCmd := "packs" + if len(args) > 0 { + subCmd = args[0] + } + + switch subCmd { + case "packs": + fmt.Println("📦 Local Packs:") + // TODO: List packs + fmt.Println(" (none)") + case "profiles": + fmt.Println("📋 Profiles:") + // TODO: List profiles + fmt.Println(" (none)") + case "collectors": + fmt.Println("🔌 Available Collectors:") + // TODO: List collectors + fmt.Println(" (none)") + default: + return fmt.Errorf("未知的子命令: %s (可选: packs, profiles, collectors)", subCmd) + } + + return nil + }, + } + + cmd.Flags().StringVarP(&output, "output", "o", "table", "输出格式 (table|json|yaml)") + cmd.Flags().BoolVar(&detailed, "detailed", false, "显示详细信息") + + return cmd +} diff --git a/cmd/devpack/commands/profile.go b/cmd/devpack/commands/profile.go new file mode 100644 index 0000000..15c8c06 --- /dev/null +++ b/cmd/devpack/commands/profile.go @@ -0,0 +1,102 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newProfileCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "profile", + Short: "管理 Profile 配置文件", + Long: `创建、编辑、删除和管理 Profile 配置方案。`, + } + + // Subcommands + cmd.AddCommand(newProfileCreateCmd()) + cmd.AddCommand(newProfileShowCmd()) + cmd.AddCommand(newProfileListCmd()) + cmd.AddCommand(newProfileDeleteCmd()) + cmd.AddCommand(newProfileUseCmd()) + + return cmd +} + +func newProfileCreateCmd() *cobra.Command { + var template string + + cmd := &cobra.Command{ + Use: "create ", + Short: "创建新 Profile", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + name := args[0] + fmt.Printf("📋 Creating profile \"%s\"...\n", name) + // TODO: Create profile + fmt.Printf("✅ Profile \"%s\" created.\n", name) + fmt.Printf("Edit with: devpack profile edit %s\n", name) + return nil + }, + } + + cmd.Flags().StringVarP(&template, "template", "t", "standard", "模板 (minimal|standard|full)") + + return cmd +} + +func newProfileShowCmd() *cobra.Command { + return &cobra.Command{ + Use: "show ", + Short: "显示 Profile 内容", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + name := args[0] + fmt.Printf("📋 Profile: %s\n", name) + // TODO: Show profile content + return nil + }, + } +} + +func newProfileListCmd() *cobra.Command { + return &cobra.Command{ + Use: "list", + Short: "列出所有 Profile", + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println("📋 Profiles:") + // TODO: List profiles + fmt.Println(" (none)") + return nil + }, + } +} + +func newProfileDeleteCmd() *cobra.Command { + return &cobra.Command{ + Use: "delete ", + Short: "删除 Profile", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + name := args[0] + fmt.Printf("🗑️ Deleting profile \"%s\"...\n", name) + // TODO: Delete profile + fmt.Printf("✅ Profile \"%s\" deleted.\n", name) + return nil + }, + } +} + +func newProfileUseCmd() *cobra.Command { + return &cobra.Command{ + Use: "use ", + Short: "设置默认 Profile", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + name := args[0] + fmt.Printf("✅ Default profile set to \"%s\".\n", name) + // TODO: Set default profile + return nil + }, + } +} diff --git a/cmd/devpack/commands/restore.go b/cmd/devpack/commands/restore.go new file mode 100644 index 0000000..131b380 --- /dev/null +++ b/cmd/devpack/commands/restore.go @@ -0,0 +1,60 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newRestoreCmd() *cobra.Command { + var ( + dryRun bool + conflict string + noRollback bool + collectors string + exclude string + parallel int + yes bool + force bool + ) + + cmd := &cobra.Command{ + Use: "restore ", + Short: "从 Pack 还原开发环境", + Long: `从指定的 Pack 还原开发环境到当前系统。`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + packName := args[0] + + if dryRun { + fmt.Printf("🔍 Dry Run — Restore Plan for \"%s\"\n\n", packName) + // TODO: Generate and display restore plan + fmt.Println("⚠ This is a dry run. No changes were made.") + fmt.Println("Run without --dry-run to apply these changes.") + return nil + } + + fmt.Printf("🚀 Restoring environment from \"%s\"...\n", packName) + // TODO: Implement restore logic + // 1. Load and verify pack + // 2. Check platform compatibility + // 3. Detect conflicts + // 4. Create restore point + // 5. Execute restore plan + // 6. Verify results + fmt.Println("✅ Environment restored successfully!") + return nil + }, + } + + cmd.Flags().BoolVar(&dryRun, "dry-run", false, "预览更改(不实际执行)") + cmd.Flags().StringVar(&conflict, "conflict", "prompt", "冲突处理策略 (skip|overwrite|merge|prompt|newest)") + cmd.Flags().BoolVar(&noRollback, "no-rollback", false, "不创建还原点") + cmd.Flags().StringVarP(&collectors, "collectors", "c", "", "只还原指定采集器") + cmd.Flags().StringVar(&exclude, "exclude", "", "排除指定采集器") + cmd.Flags().IntVar(¶llel, "parallel", 4, "并行还原数") + cmd.Flags().BoolVarP(&yes, "yes", "y", false, "跳过确认提示") + cmd.Flags().BoolVar(&force, "force", false, "强制还原") + + return cmd +} diff --git a/cmd/devpack/commands/root.go b/cmd/devpack/commands/root.go new file mode 100644 index 0000000..942b715 --- /dev/null +++ b/cmd/devpack/commands/root.go @@ -0,0 +1,80 @@ +package commands + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/user/devpack/pkg/version" +) + +var ( + cfgFile string + verbose bool + quiet bool + logLevel string + noColor bool +) + +// rootCmd represents the base command +var rootCmd = &cobra.Command{ + Use: "devpack", + Short: "DevPack - 开发环境打包迁移工具", + Long: `DevPack 是一个开发环境打包迁移工具。 +它能够扫描、捕获并打包你的完整开发环境, +在另一台同系统的电脑上一键还原。 + +让开发环境像 U 盘一样即插即用。`, + Version: version.GetVersionString(), +} + +// Execute adds all child commands to the root command and sets flags appropriately. +func Execute() error { + return rootCmd.Execute() +} + +func init() { + cobra.OnInitialize(initConfig) + + // Global flags + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径 (默认: ~/.devpack/config.yaml)") + rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "详细输出") + rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "静默模式") + rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "日志级别 (trace|debug|info|warn|error)") + rootCmd.PersistentFlags().BoolVar(&noColor, "no-color", false, "禁用彩色输出") + + // Add subcommands + rootCmd.AddCommand(newInitCmd()) + rootCmd.AddCommand(newScanCmd()) + rootCmd.AddCommand(newCaptureCmd()) + rootCmd.AddCommand(newRestoreCmd()) + rootCmd.AddCommand(newExportCmd()) + rootCmd.AddCommand(newImportCmd()) + rootCmd.AddCommand(newListCmd()) + rootCmd.AddCommand(newDiffCmd()) + rootCmd.AddCommand(newProfileCmd()) + rootCmd.AddCommand(newVersionCmd()) +} + +func initConfig() { + if cfgFile != "" { + viper.SetConfigFile(cfgFile) + } else { + home, err := os.UserHomeDir() + if err != nil { + fmt.Fprintln(os.Stderr, "Error:", err) + os.Exit(1) + } + + viper.AddConfigPath(home + "/.devpack") + viper.SetConfigName("config") + viper.SetConfigType("yaml") + } + + viper.SetEnvPrefix("DEVPACK") + viper.AutomaticEnv() + + // Read config file (ignore error if not found) + _ = viper.ReadInConfig() +} diff --git a/cmd/devpack/commands/scan.go b/cmd/devpack/commands/scan.go new file mode 100644 index 0000000..b882af0 --- /dev/null +++ b/cmd/devpack/commands/scan.go @@ -0,0 +1,44 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func newScanCmd() *cobra.Command { + var ( + collectors string + category string + profile string + output string + save string + detailed bool + ) + + cmd := &cobra.Command{ + Use: "scan", + Short: "扫描当前开发环境", + Long: `扫描当前系统的开发环境,检测已安装的工具、配置和设置。`, + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println("🔍 Scanning development environment...") + // TODO: Implement scan logic + // 1. Load profile (if specified) + // 2. Determine which collectors to run + // 3. Run collectors in parallel + // 4. Aggregate results + // 5. Display results + fmt.Println("✅ Scan complete!") + return nil + }, + } + + cmd.Flags().StringVarP(&collectors, "collectors", "c", "", "指定采集器(逗号分隔)") + cmd.Flags().StringVar(&category, "category", "", "按分类扫描 (runtime|package|editor|shell|git|env)") + cmd.Flags().StringVarP(&profile, "profile", "p", "", "使用指定 Profile 的扫描配置") + cmd.Flags().StringVarP(&output, "output", "o", "table", "输出格式 (table|json|yaml)") + cmd.Flags().StringVar(&save, "save", "", "保存扫描结果到文件") + cmd.Flags().BoolVar(&detailed, "detailed", false, "显示详细信息") + + return cmd +} diff --git a/cmd/devpack/commands/version.go b/cmd/devpack/commands/version.go new file mode 100644 index 0000000..5db78ab --- /dev/null +++ b/cmd/devpack/commands/version.go @@ -0,0 +1,18 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/user/devpack/pkg/version" +) + +func newVersionCmd() *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "显示版本信息", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version.GetFullVersionInfo()) + }, + } +} diff --git a/cmd/devpack/main.go b/cmd/devpack/main.go new file mode 100644 index 0000000..5efa874 --- /dev/null +++ b/cmd/devpack/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "os" + + "github.com/user/devpack/cmd/devpack/commands" +) + +func main() { + if err := commands.Execute(); err != nil { + os.Exit(1) + } +}