From 15cdeaa3df97a1ec768bdd930edae366ce12889b Mon Sep 17 00:00:00 2001 From: Neeladri Das Date: Tue, 27 Jan 2026 10:03:02 +0000 Subject: [PATCH 1/3] honour JULIA_DePOT_PATH rather than .julia --- CLAUDE.md | 13 +++++++++---- README.md | 2 +- auth.go | 22 ++++++++++++++++++---- run.go | 25 +++++++++++++++++++------ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index bd32ad4..f0a3712 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -224,7 +224,8 @@ The CLI provides Julia installation and execution with JuliaHub configuration: - Installs latest stable Julia version ### Julia Credentials -- **Authentication file**: Automatically creates `~/.julia/servers//auth.toml` +- **Authentication file**: Automatically creates `$JULIA_DEPOT_PATH/servers//auth.toml` (or `~/.julia/servers//auth.toml` if `JULIA_DEPOT_PATH` is not set) +- **Depot path detection**: Respects `JULIA_DEPOT_PATH` environment variable, uses first path if multiple are specified - **Atomic writes**: Uses temporary file + rename for safe credential updates - **Automatic updates**: Credentials are automatically refreshed when: - User runs `jh auth login` @@ -252,7 +253,7 @@ jh run -- --project=. --threads=4 script.jl # Run with flags ```bash jh run setup ``` -- Creates/updates `~/.julia/servers//auth.toml` with current credentials +- Creates/updates `$JULIA_DEPOT_PATH/servers//auth.toml` with current credentials (or `~/.julia/servers//auth.toml` if not set) - Does not start Julia - Useful for explicitly updating credentials @@ -265,6 +266,7 @@ jh run setup - File uploads use multipart form data with proper content types - Julia auth files use TOML format with `preferred_username` from JWT claims - Julia auth files use atomic writes (temp file + rename) to prevent corruption +- Julia credentials respect `JULIA_DEPOT_PATH` environment variable (uses first path if multiple are specified) - Julia credentials are automatically updated after login and token refresh - Git commands use `http.extraHeader` for authentication and pass through all arguments - Git credential helper provides seamless authentication for standard Git commands @@ -281,7 +283,9 @@ jh run setup The Julia credentials system consists of three main functions: 1. **`createJuliaAuthFile(server, token)`**: - - Creates `~/.julia/servers//auth.toml` with TOML-formatted credentials + - Determines depot path from `JULIA_DEPOT_PATH` environment variable (uses first path if multiple) + - Falls back to `~/.julia` if `JULIA_DEPOT_PATH` is not set + - Creates `{depot}/servers//auth.toml` with TOML-formatted credentials - Uses atomic writes: writes to temporary file, syncs, then renames - Includes all necessary fields: tokens, expiration, refresh URL, user info - Called by `setupJuliaCredentials()` and `updateJuliaCredentialsIfNeeded()` @@ -306,7 +310,8 @@ The Julia credentials system consists of three main functions: The `updateJuliaCredentialsIfNeeded(server, token)` function: - Called automatically by `ensureValidToken()` after token refresh -- Checks if `~/.julia/servers//auth.toml` exists +- Determines depot path from `JULIA_DEPOT_PATH` (same logic as `createJuliaAuthFile`) +- Checks if `{depot}/servers//auth.toml` exists - If exists, updates it with refreshed token - If not exists, does nothing (user hasn't used Julia integration yet) - Errors are silently ignored to avoid breaking token operations diff --git a/README.md b/README.md index e896a05..59ca34a 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ jh run -- --project=. --threads=4 script.jl ``` Note: Arguments after `--` are passed directly to Julia. The `jh run` command: -1. Sets up JuliaHub credentials in `~/.julia/servers//auth.toml` +1. Sets up JuliaHub credentials in `$JULIA_DEPOT_PATH/servers//auth.toml` (or `~/.julia/servers//auth.toml` if `JULIA_DEPOT_PATH` is not set) 2. Configures `JULIA_PKG_SERVER` environment variable 3. Starts Julia with your specified arguments diff --git a/auth.go b/auth.go index f8e2528..47a8244 100644 --- a/auth.go +++ b/auth.go @@ -339,13 +339,27 @@ func ensureValidToken() (*StoredToken, error) { // updateJuliaCredentialsIfNeeded updates Julia credentials if the auth file exists // This is called after token refresh to keep credentials in sync func updateJuliaCredentialsIfNeeded(server string, token *StoredToken) error { - homeDir, err := os.UserHomeDir() - if err != nil { - return err + // Determine Julia depot path + var depotPath string + if juliaDepot := os.Getenv("JULIA_DEPOT_PATH"); juliaDepot != "" { + // Use first path from JULIA_DEPOT_PATH + depotPaths := filepath.SplitList(juliaDepot) + if len(depotPaths) > 0 { + depotPath = depotPaths[0] + } + } + + // Fall back to ~/.julia if JULIA_DEPOT_PATH is not set + if depotPath == "" { + homeDir, err := os.UserHomeDir() + if err != nil { + return err + } + depotPath = filepath.Join(homeDir, ".julia") } // Check if the auth.toml file exists - authFilePath := filepath.Join(homeDir, ".julia", "servers", server, "auth.toml") + authFilePath := filepath.Join(depotPath, "servers", server, "auth.toml") if _, err := os.Stat(authFilePath); os.IsNotExist(err) { // File doesn't exist, so user hasn't used Julia integration yet return nil diff --git a/run.go b/run.go index 764c6ed..c259f7f 100644 --- a/run.go +++ b/run.go @@ -8,14 +8,27 @@ import ( ) func createJuliaAuthFile(server string, token *StoredToken) error { - // Get user home directory - homeDir, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("failed to get user home directory: %w", err) + // Determine Julia depot path + var depotPath string + if juliaDepot := os.Getenv("JULIA_DEPOT_PATH"); juliaDepot != "" { + // Use first path from JULIA_DEPOT_PATH (paths are separated by : on Unix, ; on Windows) + depotPaths := filepath.SplitList(juliaDepot) + if len(depotPaths) > 0 { + depotPath = depotPaths[0] + } + } + + // Fall back to ~/.julia if JULIA_DEPOT_PATH is not set + if depotPath == "" { + homeDir, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to get user home directory: %w", err) + } + depotPath = filepath.Join(homeDir, ".julia") } - // Create ~/.julia/servers/{server}/ directory - serverDir := filepath.Join(homeDir, ".julia", "servers", server) + // Create {depot}/servers/{server}/ directory + serverDir := filepath.Join(depotPath, "servers", server) if err := os.MkdirAll(serverDir, 0755); err != nil { return fmt.Errorf("failed to create server directory: %w", err) } From c894c3ba73187e8334e84f33676a9599f1c4d23a Mon Sep 17 00:00:00 2001 From: Neeladri Das Date: Tue, 10 Feb 2026 07:16:08 +0000 Subject: [PATCH 2/3] added reusable get julia depot path func --- run.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/run.go b/run.go index c259f7f..c1ddce3 100644 --- a/run.go +++ b/run.go @@ -7,8 +7,7 @@ import ( "path/filepath" ) -func createJuliaAuthFile(server string, token *StoredToken) error { - // Determine Julia depot path +func getJuliaDepotPath() (string, error) { var depotPath string if juliaDepot := os.Getenv("JULIA_DEPOT_PATH"); juliaDepot != "" { // Use first path from JULIA_DEPOT_PATH (paths are separated by : on Unix, ; on Windows) @@ -22,11 +21,20 @@ func createJuliaAuthFile(server string, token *StoredToken) error { if depotPath == "" { homeDir, err := os.UserHomeDir() if err != nil { - return fmt.Errorf("failed to get user home directory: %w", err) + return "", fmt.Errorf("failed to get user home directory: %w", err) } depotPath = filepath.Join(homeDir, ".julia") } + return depotPath, nil +} + +func createJuliaAuthFile(server string, token *StoredToken) error { + depotPath, err := getJuliaDepotPath() + if err != nil { + return err + } + // Create {depot}/servers/{server}/ directory serverDir := filepath.Join(depotPath, "servers", server) if err := os.MkdirAll(serverDir, 0755); err != nil { From 892aba6847095ba906f61012822bbeec6c7f1cef Mon Sep 17 00:00:00 2001 From: Neeladri Das Date: Wed, 11 Feb 2026 07:24:33 +0000 Subject: [PATCH 3/3] refactor --- auth.go | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/auth.go b/auth.go index 47a8244..3430860 100644 --- a/auth.go +++ b/auth.go @@ -340,22 +340,9 @@ func ensureValidToken() (*StoredToken, error) { // This is called after token refresh to keep credentials in sync func updateJuliaCredentialsIfNeeded(server string, token *StoredToken) error { // Determine Julia depot path - var depotPath string - if juliaDepot := os.Getenv("JULIA_DEPOT_PATH"); juliaDepot != "" { - // Use first path from JULIA_DEPOT_PATH - depotPaths := filepath.SplitList(juliaDepot) - if len(depotPaths) > 0 { - depotPath = depotPaths[0] - } - } - - // Fall back to ~/.julia if JULIA_DEPOT_PATH is not set - if depotPath == "" { - homeDir, err := os.UserHomeDir() - if err != nil { - return err - } - depotPath = filepath.Join(homeDir, ".julia") + depotPath, err := getJuliaDepotPath() + if err != nil { + return err } // Check if the auth.toml file exists