diff --git a/docs/project-setup.md b/docs/project-setup.md index c18bbdc..5bd49aa 100644 --- a/docs/project-setup.md +++ b/docs/project-setup.md @@ -229,7 +229,7 @@ The lock file is automatically generated and should be committed to version cont ```json { "lockVersion": 1, - "hemlock": "1.0.0", + "hemlock": "2.7.0", "dependencies": { "hemlang/sprout": { "version": "2.1.0", diff --git a/package.json b/package.json index 3fb646a..d087bcc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hemlang/hpm", - "version": "1.2.0", + "version": "1.2.1", "description": "Hemlock Package Manager - A package manager for the Hemlock programming language", "author": "Hemlock Team", "license": "MIT", diff --git a/src/github.hml b/src/github.hml index e0e382f..891caa3 100644 --- a/src/github.hml +++ b/src/github.hml @@ -54,6 +54,16 @@ export fn get_token() { return null; } +// Perform a GET, converting thrown network errors (connection failure, +// timeout) into a retryable status-0 response so retry loops can handle them +fn try_get(url: string, headers) { + try { + return get(url, headers); + } catch (e) { + return { status_code: 0, headers: [], body: "" }; + } +} + // Make an authenticated GitHub API request with retry logic fn github_request(url: string) { let headers = []; @@ -70,7 +80,7 @@ fn github_request(url: string) { let backoff_s = INITIAL_BACKOFF_S; while (retries <= MAX_RETRIES) { - let response = get(url, headers); + let response = try_get(url, headers); if (response.status_code == 403) { // Rate limit - retry with exponential backoff @@ -95,6 +105,9 @@ fn github_request(url: string) { backoff_s = backoff_s * 2; continue; } + if (response.status_code == 0) { + throw "GitHub API request failed (network error) after " + MAX_RETRIES + " retries"; + } throw "GitHub API error: HTTP " + response.status_code + " after " + MAX_RETRIES + " retries"; } @@ -292,9 +305,9 @@ export fn repo_exists(owner: string, repo: string): bool { let backoff_s = INITIAL_BACKOFF_S; while (retries <= MAX_RETRIES) { - let response = get(url, headers); + let response = try_get(url, headers); - // Retry on rate limit or server errors + // Retry on rate limit, server errors, or network failures if (response.status_code == 403 || response.status_code >= 500 || response.status_code == 0) { if (retries < MAX_RETRIES) { retries = retries + 1; diff --git a/src/lockfile.hml b/src/lockfile.hml index c02ca9e..3c32e47 100644 --- a/src/lockfile.hml +++ b/src/lockfile.hml @@ -10,7 +10,7 @@ let LOCK_VERSION = 1; export fn create_empty() { return { lockVersion: LOCK_VERSION, - hemlock: "1.1.0", + hemlock: "2.7.0", dependencies: {} }; } diff --git a/src/main.hml b/src/main.hml index 6760d20..87f3ce3 100644 --- a/src/main.hml +++ b/src/main.hml @@ -15,7 +15,7 @@ import * as installer from "./installer.hml"; import * as cache from "./cache.hml"; // Version info -let HPM_VERSION = "1.2.0"; +let HPM_VERSION = "1.2.1"; github.init(HPM_VERSION); // Exit codes diff --git a/test/test_lockfile.hml b/test/test_lockfile.hml index 4596cac..25cf635 100644 --- a/test/test_lockfile.hml +++ b/test/test_lockfile.hml @@ -9,7 +9,7 @@ export fn run() { test("creates empty lockfile", fn() { let lock = lockfile.create_empty(); assert_eq(lock.lockVersion, 1, "lockVersion"); - assert_eq(lock.hemlock, "1.1.0", "hemlock"); + assert_eq(lock.hemlock, "2.7.0", "hemlock"); assert_not_null(lock.dependencies, "dependencies"); });