Skip to main content

codex_cli/auth/
sync.rs

1use anyhow::Result;
2use nils_common::fs;
3use nils_common::provider_runtime::persistence::{
4    SyncSecretsError, TimestampPolicy, sync_auth_to_matching_secrets,
5};
6use serde_json::json;
7
8use crate::auth::output::{self, AuthSyncResult};
9use crate::paths;
10use crate::provider_profile::CODEX_PROVIDER_PROFILE;
11
12pub fn run() -> Result<i32> {
13    run_with_json(false)
14}
15
16pub fn run_with_json(output_json: bool) -> Result<i32> {
17    let auth_file = match paths::resolve_auth_file() {
18        Some(path) => path,
19        None => {
20            if output_json {
21                output::emit_result(
22                    "auth sync",
23                    AuthSyncResult {
24                        auth_file: String::new(),
25                        synced: 0,
26                        skipped: 0,
27                        failed: 0,
28                        updated_files: Vec::new(),
29                    },
30                )?;
31            }
32            return Ok(0);
33        }
34    };
35
36    let sync_result = match sync_auth_to_matching_secrets(
37        &CODEX_PROVIDER_PROFILE,
38        &auth_file,
39        fs::SECRET_FILE_MODE,
40        TimestampPolicy::Strict,
41    ) {
42        Ok(result) => result,
43        Err(SyncSecretsError::HashAuthFile { path, .. })
44        | Err(SyncSecretsError::HashSecretFile { path, .. }) => {
45            if output_json {
46                output::emit_error(
47                    "auth sync",
48                    "hash-failed",
49                    format!("failed to hash {}", path.display()),
50                    Some(json!({
51                        "path": path.display().to_string(),
52                    })),
53                )?;
54            } else {
55                eprintln!("codex: failed to hash {}", path.display());
56            }
57            return Ok(1);
58        }
59        Err(err) => return Err(err.into()),
60    };
61
62    if !sync_result.auth_file_present {
63        if output_json {
64            output::emit_result(
65                "auth sync",
66                AuthSyncResult {
67                    auth_file: auth_file.display().to_string(),
68                    synced: 0,
69                    skipped: 1,
70                    failed: 0,
71                    updated_files: Vec::new(),
72                },
73            )?;
74        }
75        return Ok(0);
76    }
77
78    if !sync_result.auth_identity_present {
79        if output_json {
80            output::emit_result(
81                "auth sync",
82                AuthSyncResult {
83                    auth_file: auth_file.display().to_string(),
84                    synced: 0,
85                    skipped: 1,
86                    failed: 0,
87                    updated_files: Vec::new(),
88                },
89            )?;
90        }
91        return Ok(0);
92    }
93
94    let synced = sync_result.synced;
95    let skipped = sync_result.skipped;
96    let failed = 0usize;
97    let updated_files = sync_result
98        .updated_files
99        .into_iter()
100        .map(|path| path.display().to_string())
101        .collect();
102
103    if output_json {
104        output::emit_result(
105            "auth sync",
106            AuthSyncResult {
107                auth_file: auth_file.display().to_string(),
108                synced,
109                skipped,
110                failed,
111                updated_files,
112            },
113        )?;
114    }
115
116    Ok(0)
117}