11const std = @import ("std" );
2+ const builtin = @import ("builtin" );
23const account_api = @import ("account_api.zig" );
34const account_name_refresh = @import ("account_name_refresh.zig" );
45const cli = @import ("cli.zig" );
@@ -1530,8 +1531,16 @@ fn handleList(allocator: std.mem.Allocator, codex_home: []const u8, opts: cli.Li
15301531}
15311532
15321533fn handleLogin (allocator : std.mem.Allocator , codex_home : []const u8 , opts : cli.LoginOptions ) ! void {
1533- try cli .runCodexLogin (opts );
1534- const auth_path = try registry .activeAuthPath (allocator , codex_home );
1534+ const login_home = try createTempLoginCodexHome (allocator );
1535+ defer {
1536+ std .fs .cwd ().deleteTree (login_home ) catch | err | {
1537+ std .log .warn ("failed to remove temporary Codex login home `{s}`: {s}" , .{ login_home , @errorName (err ) });
1538+ };
1539+ allocator .free (login_home );
1540+ }
1541+
1542+ try cli .runCodexLoginWithCodexHome (allocator , opts , login_home );
1543+ const auth_path = try registry .activeAuthPath (allocator , login_home );
15351544 defer allocator .free (auth_path );
15361545
15371546 const info = try auth .parseAuthInfo (allocator , auth_path );
@@ -1540,6 +1549,8 @@ fn handleLogin(allocator: std.mem.Allocator, codex_home: []const u8, opts: cli.L
15401549 var reg = try registry .loadRegistry (allocator , codex_home );
15411550 defer reg .deinit (allocator );
15421551
1552+ _ = try registry .syncActiveAccountFromAuth (allocator , codex_home , & reg );
1553+
15431554 const email = info .email orelse return error .MissingEmail ;
15441555 _ = email ;
15451556 const record_key = info .record_key orelse return error .MissingChatgptUserId ;
@@ -1548,6 +1559,9 @@ fn handleLogin(allocator: std.mem.Allocator, codex_home: []const u8, opts: cli.L
15481559
15491560 try registry .ensureAccountsDir (allocator , codex_home );
15501561 try registry .copyFile (auth_path , dest );
1562+ const active_auth_path = try registry .activeAuthPath (allocator , codex_home );
1563+ defer allocator .free (active_auth_path );
1564+ try registry .copyFile (auth_path , active_auth_path );
15511565
15521566 const record = try registry .accountFromAuth (allocator , "" , & info );
15531567 try registry .upsertAccount (allocator , & reg , record );
@@ -1556,6 +1570,56 @@ fn handleLogin(allocator: std.mem.Allocator, codex_home: []const u8, opts: cli.L
15561570 try registry .saveRegistry (allocator , codex_home , & reg );
15571571}
15581572
1573+ fn createTempLoginCodexHome (allocator : std.mem.Allocator ) ! []u8 {
1574+ const base = try tempBasePathAlloc (allocator );
1575+ defer allocator .free (base );
1576+ var counter : usize = 0 ;
1577+ while (counter < 100 ) : (counter += 1 ) {
1578+ const path = try std .fmt .allocPrint (
1579+ allocator ,
1580+ "{s}{c}codex-auth-login-{d}-{d}" ,
1581+ .{ base , std .fs .path .sep , std .time .nanoTimestamp (), counter },
1582+ );
1583+ std .fs .cwd ().makePath (path ) catch | err | switch (err ) {
1584+ error .PathAlreadyExists = > {
1585+ allocator .free (path );
1586+ continue ;
1587+ },
1588+ else = > {
1589+ allocator .free (path );
1590+ return err ;
1591+ },
1592+ };
1593+ return path ;
1594+ }
1595+ return error .PathAlreadyExists ;
1596+ }
1597+
1598+ fn tempBasePathAlloc (allocator : std.mem.Allocator ) ! []u8 {
1599+ if (builtin .os .tag == .windows ) {
1600+ if (try getNonEmptyEnvVarOwned (allocator , "TEMP" )) | path | return path ;
1601+ if (try getNonEmptyEnvVarOwned (allocator , "TMP" )) | path | return path ;
1602+ if (try getNonEmptyEnvVarOwned (allocator , "TMPDIR" )) | path | return path ;
1603+ return allocator .dupe (u8 , "C:\\ Temp" );
1604+ }
1605+ if (try getNonEmptyEnvVarOwned (allocator , "TMPDIR" )) | path | return path ;
1606+ if (try getNonEmptyEnvVarOwned (allocator , "TMP" )) | path | return path ;
1607+ if (try getNonEmptyEnvVarOwned (allocator , "TEMP" )) | path | return path ;
1608+ return allocator .dupe (u8 , "/tmp" );
1609+ }
1610+
1611+ fn getNonEmptyEnvVarOwned (allocator : std.mem.Allocator , name : []const u8 ) ! ? []u8 {
1612+ const value = std .process .getEnvVarOwned (allocator , name ) catch | err | switch (err ) {
1613+ error .EnvironmentVariableNotFound = > return null ,
1614+ else = > return err ,
1615+ };
1616+ if (value .len == 0 ) {
1617+ allocator .free (value );
1618+ return null ;
1619+ }
1620+ return value ;
1621+ }
1622+
15591623fn handleImport (allocator : std.mem.Allocator , codex_home : []const u8 , opts : cli.ImportOptions ) ! void {
15601624 if (opts .purge ) {
15611625 var report = try registry .purgeRegistryFromImportSource (allocator , codex_home , opts .auth_path , opts .alias );
0 commit comments