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}