installBashCompletion installs bash completion
(verbose bool, cmd *cobra.Command)
| 123 | |
| 124 | // installBashCompletion installs bash completion |
| 125 | func installBashCompletion(verbose bool, cmd *cobra.Command) error { |
| 126 | shellCompletionLog.Print("Installing bash completion") |
| 127 | |
| 128 | // Generate completion script using Cobra |
| 129 | var buf bytes.Buffer |
| 130 | if err := cmd.GenBashCompletion(&buf); err != nil { |
| 131 | return fmt.Errorf("failed to generate bash completion: %w", err) |
| 132 | } |
| 133 | |
| 134 | completionScript := buf.String() |
| 135 | |
| 136 | // Determine installation path |
| 137 | var completionPath string |
| 138 | homeDir, err := os.UserHomeDir() |
| 139 | if err != nil { |
| 140 | return fmt.Errorf("failed to get home directory: %w", err) |
| 141 | } |
| 142 | |
| 143 | // Try to determine the best location for bash completions |
| 144 | if runtime.GOOS == "darwin" { |
| 145 | // macOS with Homebrew |
| 146 | brewPrefix := os.Getenv("HOMEBREW_PREFIX") |
| 147 | if brewPrefix == "" { |
| 148 | // Try common locations |
| 149 | for _, prefix := range []string{constants.HomebrewPrefix, constants.UsrLocalPrefix} { |
| 150 | if fileutil.DirExists(filepath.Join(prefix, "etc", "bash_completion.d")) { |
| 151 | brewPrefix = prefix |
| 152 | break |
| 153 | } |
| 154 | } |
| 155 | } |
| 156 | if brewPrefix != "" { |
| 157 | completionPath = filepath.Join(brewPrefix, "etc", "bash_completion.d", "gh-aw") |
| 158 | } else { |
| 159 | completionPath = filepath.Join(homeDir, ".bash_completion.d", "gh-aw") |
| 160 | } |
| 161 | } else { |
| 162 | // Linux |
| 163 | if fileutil.DirExists(constants.BashCompletionDir) { |
| 164 | completionPath = constants.BashCompletionGhAwPath |
| 165 | } else { |
| 166 | completionPath = filepath.Join(homeDir, ".bash_completion.d", "gh-aw") |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | // Create directory if needed (for user-level installations) |
| 171 | completionDir := filepath.Dir(completionPath) |
| 172 | if strings.HasPrefix(completionDir, homeDir) { |
| 173 | // Use restrictive permissions (0750) following principle of least privilege |
| 174 | if err := os.MkdirAll(completionDir, constants.DirPermSensitive); err != nil { |
| 175 | return fmt.Errorf("failed to create completion directory: %w", err) |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | // Try to write completion file |
| 180 | // Use restrictive permissions (0600) following principle of least privilege |
| 181 | err = os.WriteFile(completionPath, []byte(completionScript), constants.FilePermSensitive) |
| 182 | if err != nil && strings.HasPrefix(completionPath, "/etc") { |
no test coverage detected