@@ -44,144 +44,161 @@ int accounts_init(gitswitch_ctx_t *ctx) { |
| 44 | /* Switch to specified account with SSH isolation and validation */ | 44 | /* Switch to specified account with SSH isolation and validation */ |
| 45 | int accounts_switch(gitswitch_ctx_t *ctx, const char *identifier) { | 45 | int accounts_switch(gitswitch_ctx_t *ctx, const char *identifier) { |
| 46 | account_t *account; | 46 | account_t *account; |
| 47 | - | 47 | + const char *scope_str; |
| | 48 | + bool ssh_ok = false; |
| | 49 | + bool gpg_ok = false; |
| | 50 | + |
| 48 | if (!ctx || !identifier) { | 51 | if (!ctx || !identifier) { |
| 49 | set_error(ERR_INVALID_ARGS, "Invalid arguments to accounts_switch"); | 52 | set_error(ERR_INVALID_ARGS, "Invalid arguments to accounts_switch"); |
| 50 | return -1; | 53 | return -1; |
| 51 | } | 54 | } |
| 52 | - | 55 | + |
| 53 | /* Find the account */ | 56 | /* Find the account */ |
| 54 | account = config_find_account(ctx, identifier); | 57 | account = config_find_account(ctx, identifier); |
| 55 | if (!account) { | 58 | if (!account) { |
| 56 | set_error(ERR_ACCOUNT_NOT_FOUND, "Account not found: %s", identifier); | 59 | set_error(ERR_ACCOUNT_NOT_FOUND, "Account not found: %s", identifier); |
| 57 | return -1; | 60 | return -1; |
| 58 | } | 61 | } |
| 59 | - | 62 | + |
| 60 | /* Basic validation */ | 63 | /* Basic validation */ |
| 61 | if (!validate_name(account->name) || !validate_email(account->email)) { | 64 | if (!validate_name(account->name) || !validate_email(account->email)) { |
| 62 | set_error(ERR_ACCOUNT_INVALID, "Account has invalid name or email"); | 65 | set_error(ERR_ACCOUNT_INVALID, "Account has invalid name or email"); |
| 63 | return -1; | 66 | return -1; |
| 64 | } | 67 | } |
| 65 | - | 68 | + |
| 66 | /* Determine git scope - use account preference or context default */ | 69 | /* Determine git scope - use account preference or context default */ |
| 67 | git_scope_t scope = account->preferred_scope; | 70 | git_scope_t scope = account->preferred_scope; |
| 68 | if (scope == GIT_SCOPE_LOCAL && !git_is_repository()) { | 71 | if (scope == GIT_SCOPE_LOCAL && !git_is_repository()) { |
| 69 | - log_warning("Account prefers local scope, but not in git repository. Using global scope."); | 72 | + display_warning("Not in a git repository, using global scope instead of local"); |
| 70 | scope = GIT_SCOPE_GLOBAL; | 73 | scope = GIT_SCOPE_GLOBAL; |
| 71 | } | 74 | } |
| 72 | - | 75 | + scope_str = (scope == GIT_SCOPE_LOCAL) ? "local" : "global"; |
| | 76 | + |
| 73 | /* Initialize git operations if not already done */ | 77 | /* Initialize git operations if not already done */ |
| 74 | if (git_ops_init() != 0) { | 78 | if (git_ops_init() != 0) { |
| 75 | set_error(ERR_GIT_CONFIG_FAILED, "Failed to initialize git operations"); | 79 | set_error(ERR_GIT_CONFIG_FAILED, "Failed to initialize git operations"); |
| 76 | return -1; | 80 | return -1; |
| 77 | } | 81 | } |
| 78 | - | 82 | + |
| | 83 | + /* Show what we're doing */ |
| | 84 | + printf("\nSwitching to account: %s <%s>\n", account->name, account->email); |
| | 85 | + |
| 79 | /* If not in dry-run mode, actually set git configuration */ | 86 | /* If not in dry-run mode, actually set git configuration */ |
| 80 | if (!ctx->config.dry_run) { | 87 | if (!ctx->config.dry_run) { |
| 81 | - log_info("Setting git configuration for account: %s (%s scope)", | 88 | + log_info("Setting git configuration for account: %s (%s scope)", |
| 82 | - account->name, scope == GIT_SCOPE_LOCAL ? "local" : "global"); | 89 | + account->name, scope_str); |
| 83 | - | 90 | + |
| 84 | if (git_set_config(account, scope) != 0) { | 91 | if (git_set_config(account, scope) != 0) { |
| 85 | - set_error(ERR_GIT_CONFIG_FAILED, "Failed to set git configuration: %s", | 92 | + set_error(ERR_GIT_CONFIG_FAILED, "Failed to set git configuration: %s", |
| 86 | get_last_error()->message); | 93 | get_last_error()->message); |
| 87 | return -1; | 94 | return -1; |
| 88 | } | 95 | } |
| 89 | - | 96 | + printf(" [OK] Git config set (%s scope)\n", scope_str); |
| | 97 | + |
| 90 | /* Validate the configuration was set correctly */ | 98 | /* Validate the configuration was set correctly */ |
| 91 | if (git_test_config(account, scope) != 0) { | 99 | if (git_test_config(account, scope) != 0) { |
| 92 | log_warning("Git configuration validation failed: %s", get_last_error()->message); | 100 | log_warning("Git configuration validation failed: %s", get_last_error()->message); |
| 93 | /* Don't fail completely, just warn */ | 101 | /* Don't fail completely, just warn */ |
| 94 | } | 102 | } |
| 95 | - | 103 | + |
| 96 | /* Handle SSH agent isolation if SSH is enabled */ | 104 | /* Handle SSH agent isolation if SSH is enabled */ |
| 97 | if (account->ssh_enabled && strlen(account->ssh_key_path) > 0) { | 105 | if (account->ssh_enabled && strlen(account->ssh_key_path) > 0) { |
| 98 | log_info("Setting up SSH isolation for account: %s", account->name); | 106 | log_info("Setting up SSH isolation for account: %s", account->name); |
| 99 | - | 107 | + |
| 100 | /* Initialize SSH manager with isolated agents */ | 108 | /* Initialize SSH manager with isolated agents */ |
| 101 | ssh_config_t ssh_config = {0}; | 109 | ssh_config_t ssh_config = {0}; |
| 102 | if (ssh_manager_init(&ssh_config, SSH_AGENT_ISOLATED) != 0) { | 110 | if (ssh_manager_init(&ssh_config, SSH_AGENT_ISOLATED) != 0) { |
| | 111 | + printf(" [!!] SSH agent failed to start\n"); |
| 103 | log_warning("Failed to initialize SSH manager: %s", get_last_error()->message); | 112 | log_warning("Failed to initialize SSH manager: %s", get_last_error()->message); |
| 104 | } else { | 113 | } else { |
| 105 | /* Switch to account's SSH configuration */ | 114 | /* Switch to account's SSH configuration */ |
| 106 | if (ssh_switch_account(&ssh_config, account) != 0) { | 115 | if (ssh_switch_account(&ssh_config, account) != 0) { |
| | 116 | + printf(" [!!] SSH key failed to load\n"); |
| 107 | log_warning("Failed to switch SSH configuration: %s", get_last_error()->message); | 117 | log_warning("Failed to switch SSH configuration: %s", get_last_error()->message); |
| 108 | /* Clean up SSH manager on failure */ | 118 | /* Clean up SSH manager on failure */ |
| 109 | ssh_manager_cleanup(&ssh_config); | 119 | ssh_manager_cleanup(&ssh_config); |
| 110 | } else { | 120 | } else { |
| | 121 | + ssh_ok = true; |
| | 122 | + printf(" [OK] SSH key loaded\n"); |
| 111 | log_info("SSH isolation activated for account: %s", account->name); | 123 | log_info("SSH isolation activated for account: %s", account->name); |
| 112 | - | 124 | + |
| 113 | /* Test SSH connection if connection testing is available */ | 125 | /* Test SSH connection if connection testing is available */ |
| 114 | if (strlen(account->ssh_host_alias) > 0) { | 126 | if (strlen(account->ssh_host_alias) > 0) { |
| 115 | if (ssh_test_connection(account, account->ssh_host_alias) == 0) { | 127 | if (ssh_test_connection(account, account->ssh_host_alias) == 0) { |
| 116 | - log_info("SSH connection test passed for %s", account->ssh_host_alias); | 128 | + printf(" [OK] SSH connection verified (%s)\n", account->ssh_host_alias); |
| 117 | } else { | 129 | } else { |
| 118 | - log_warning("SSH connection test failed for %s", account->ssh_host_alias); | 130 | + printf(" [--] SSH connection test skipped (%s unreachable)\n", account->ssh_host_alias); |
| 119 | } | 131 | } |
| 120 | } else { | 132 | } else { |
| 121 | /* Test with default GitHub host (git@ is required for GitHub SSH) */ | 133 | /* Test with default GitHub host (git@ is required for GitHub SSH) */ |
| 122 | if (ssh_test_connection(account, "git@github.com") == 0) { | 134 | if (ssh_test_connection(account, "git@github.com") == 0) { |
| 123 | - log_info("SSH connection test passed for github.com"); | 135 | + printf(" [OK] SSH connection verified (github.com)\n"); |
| 124 | - } else { | | |
| 125 | - log_debug("SSH connection test failed for github.com (this may be normal)"); | | |
| 126 | } | 136 | } |
| | 137 | + /* Silently skip if GitHub unreachable - not an error */ |
| 127 | } | 138 | } |
| 128 | } | 139 | } |
| 129 | } | 140 | } |
| 130 | } | 141 | } |
| 131 | - | 142 | + |
| 132 | /* Handle GPG environment isolation if GPG is enabled */ | 143 | /* Handle GPG environment isolation if GPG is enabled */ |
| 133 | if (account->gpg_enabled && strlen(account->gpg_key_id) > 0) { | 144 | if (account->gpg_enabled && strlen(account->gpg_key_id) > 0) { |
| 134 | log_info("Setting up GPG isolation for account: %s", account->name); | 145 | log_info("Setting up GPG isolation for account: %s", account->name); |
| 135 | - | 146 | + |
| 136 | /* Initialize GPG manager with isolated environments */ | 147 | /* Initialize GPG manager with isolated environments */ |
| 137 | gpg_config_t gpg_config = {0}; | 148 | gpg_config_t gpg_config = {0}; |
| 138 | if (gpg_manager_init(&gpg_config, GPG_MODE_ISOLATED) != 0) { | 149 | if (gpg_manager_init(&gpg_config, GPG_MODE_ISOLATED) != 0) { |
| | 150 | + printf(" [!!] GPG manager failed to initialize\n"); |
| 139 | log_warning("Failed to initialize GPG manager: %s", get_last_error()->message); | 151 | log_warning("Failed to initialize GPG manager: %s", get_last_error()->message); |
| 140 | } else { | 152 | } else { |
| 141 | /* Switch to account's GPG configuration */ | 153 | /* Switch to account's GPG configuration */ |
| 142 | if (gpg_switch_account(&gpg_config, account) != 0) { | 154 | if (gpg_switch_account(&gpg_config, account) != 0) { |
| | 155 | + printf(" [!!] GPG key failed to activate\n"); |
| 143 | log_warning("Failed to switch GPG configuration: %s", get_last_error()->message); | 156 | log_warning("Failed to switch GPG configuration: %s", get_last_error()->message); |
| 144 | /* Clean up GPG manager on failure */ | 157 | /* Clean up GPG manager on failure */ |
| 145 | gpg_manager_cleanup(&gpg_config); | 158 | gpg_manager_cleanup(&gpg_config); |
| 146 | } else { | 159 | } else { |
| 147 | log_info("GPG isolation activated for account: %s", account->name); | 160 | log_info("GPG isolation activated for account: %s", account->name); |
| 148 | - | 161 | + |
| 149 | /* Configure git GPG signing */ | 162 | /* Configure git GPG signing */ |
| 150 | if (gpg_configure_git_signing(&gpg_config, account, scope) != 0) { | 163 | if (gpg_configure_git_signing(&gpg_config, account, scope) != 0) { |
| | 164 | + printf(" [!!] GPG signing config failed\n"); |
| 151 | log_warning("Failed to configure git GPG signing: %s", get_last_error()->message); | 165 | log_warning("Failed to configure git GPG signing: %s", get_last_error()->message); |
| 152 | } else { | 166 | } else { |
| | 167 | + gpg_ok = true; |
| | 168 | + printf(" [OK] GPG signing enabled (key: %s)\n", account->gpg_key_id); |
| 153 | log_info("Git GPG signing configured for account: %s", account->name); | 169 | log_info("Git GPG signing configured for account: %s", account->name); |
| 154 | } | 170 | } |
| 155 | } | 171 | } |
| 156 | } | 172 | } |
| 157 | } | 173 | } |
| 158 | } else { | 174 | } else { |
| 159 | - display_info("DRY RUN: Would set git configuration for %s", account->name); | 175 | + printf(" [--] DRY RUN: Would set git config (%s scope)\n", scope_str); |
| 160 | if (account->ssh_enabled && strlen(account->ssh_key_path) > 0) { | 176 | if (account->ssh_enabled && strlen(account->ssh_key_path) > 0) { |
| 161 | - display_info("DRY RUN: Would activate SSH isolation for %s", account->ssh_key_path); | 177 | + printf(" [--] DRY RUN: Would load SSH key\n"); |
| 162 | } | 178 | } |
| 163 | if (account->gpg_enabled && strlen(account->gpg_key_id) > 0) { | 179 | if (account->gpg_enabled && strlen(account->gpg_key_id) > 0) { |
| 164 | - display_info("DRY RUN: Would activate GPG isolation for key %s", account->gpg_key_id); | 180 | + printf(" [--] DRY RUN: Would enable GPG signing\n"); |
| 165 | } | 181 | } |
| 166 | } | 182 | } |
| 167 | - | 183 | + |
| 168 | /* Test SSH functionality if enabled (basic validation) */ | 184 | /* Test SSH functionality if enabled (basic validation) */ |
| 169 | - if (account->ssh_enabled && strlen(account->ssh_key_path) > 0) { | 185 | + if (account->ssh_enabled && strlen(account->ssh_key_path) > 0 && !ssh_ok) { |
| 170 | if (test_ssh_key_functionality(account) != 0) { | 186 | if (test_ssh_key_functionality(account) != 0) { |
| 171 | log_warning("SSH key test failed for account: %s", account->name); | 187 | log_warning("SSH key test failed for account: %s", account->name); |
| 172 | } | 188 | } |
| 173 | } | 189 | } |
| 174 | - | 190 | + |
| 175 | /* Test GPG functionality if enabled */ | 191 | /* Test GPG functionality if enabled */ |
| 176 | - if (account->gpg_enabled && strlen(account->gpg_key_id) > 0) { | 192 | + if (account->gpg_enabled && strlen(account->gpg_key_id) > 0 && !gpg_ok) { |
| 177 | if (test_gpg_key_functionality(account) != 0) { | 193 | if (test_gpg_key_functionality(account) != 0) { |
| 178 | log_warning("GPG key test failed for account: %s", account->name); | 194 | log_warning("GPG key test failed for account: %s", account->name); |
| 179 | } | 195 | } |
| 180 | } | 196 | } |
| 181 | - | 197 | + |
| 182 | /* Set as current account */ | 198 | /* Set as current account */ |
| 183 | ctx->current_account = account; | 199 | ctx->current_account = account; |
| 184 | - | 200 | + |
| | 201 | + printf("\n"); |
| 185 | log_info("Successfully switched to account: %s (%s)", account->name, account->description); | 202 | log_info("Successfully switched to account: %s (%s)", account->name, account->description); |
| 186 | return 0; | 203 | return 0; |
| 187 | } | 204 | } |