add checking for new mod versions
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
|
||||
[dependencies]
|
||||
extramath = "https://gitea.pockle.world/john/extramath@master"
|
||||
@@ -1,5 +1,6 @@
|
||||
[modules]
|
||||
[modules.extramath]
|
||||
hash = "4244JXYZT7IMYQFYXOSPRK7VFCH4FBYQCQ5FCKYXMGA4QMN6RMPA===="
|
||||
hash = "MCLZT3JABTAENS4WVXKGWJ7JPBLZER4YQ5VN2PE7ZD2Z4WYGTIMA===="
|
||||
url = "https://gitea.pockle.world/john/extramath@master"
|
||||
downloaded = "Monday June 2 10:41:16.23 AM -5 2025 AD"
|
||||
downloaded = "Monday June 2 12:07:20.42 PM -5 2025 AD"
|
||||
commit = "84d81a19a8455bcf8dc494739e9e6d545df6ff2c"
|
||||
@@ -12,34 +12,9 @@ if (!io.exists('.cell/build')) {
|
||||
|
||||
log.console("Cleaning build artifacts...")
|
||||
|
||||
// Recursively delete directory contents
|
||||
function remove_dir(path) {
|
||||
var files = io.enumerate(path, false) // non-recursive first
|
||||
|
||||
// Delete all files and subdirectories
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i]
|
||||
if (io.is_directory(file)) {
|
||||
remove_dir(file) // Recurse into subdirectory
|
||||
} else {
|
||||
try {
|
||||
io.rm(file)
|
||||
} catch (e) {
|
||||
log.error("Failed to remove " + file + ": " + e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove the empty directory
|
||||
try {
|
||||
io.rm(path)
|
||||
} catch (e) {
|
||||
log.error("Failed to remove directory " + path + ": " + e)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the build directory
|
||||
try {
|
||||
io.rmdir('.cell/build')
|
||||
remove_dir('.cell/build')
|
||||
log.console("Build directory removed")
|
||||
} catch (e) {
|
||||
|
||||
@@ -250,6 +250,7 @@ if (io.exists(configPath)) {
|
||||
}
|
||||
|
||||
globalThis.json = use('json')
|
||||
globalThis.text = use('text')
|
||||
var time = use('time')
|
||||
|
||||
var blob = use('blob')
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
var io = this
|
||||
|
||||
function remove_dir(path) {
|
||||
var files = io.enumerate(path, false) // non-recursive first
|
||||
|
||||
// Delete all files and subdirectories
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i]
|
||||
if (io.is_directory(file)) {
|
||||
remove_dir(file) // Recurse into subdirectory
|
||||
} else {
|
||||
try {
|
||||
io.rm(file)
|
||||
} catch (e) {
|
||||
log.error("Failed to remove " + file + ": " + e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove the empty directory
|
||||
try {
|
||||
io.rm(path)
|
||||
} catch (e) {
|
||||
log.error("Failed to remove directory " + path + ": " + e)
|
||||
}
|
||||
}
|
||||
|
||||
io.rmdir = remove_dir
|
||||
|
||||
io.rm[cell.DOC] = `Remove the file or empty directory at the given path.
|
||||
|
||||
:param path: The file or empty directory to remove. Must be empty if a directory.
|
||||
|
||||
@@ -36,6 +36,22 @@ uses.download = function()
|
||||
|
||||
var zip
|
||||
var need_download = false
|
||||
var remote_commit = null
|
||||
|
||||
// Check remote commit if this is a git repository
|
||||
var api_url = shop.get_api_url(mods[mod])
|
||||
if (api_url) {
|
||||
log.console(`${mod}: checking remote commit...`)
|
||||
try {
|
||||
var api_response = http.fetch(api_url)
|
||||
remote_commit = shop.extract_commit_hash(mods[mod], text(api_response))
|
||||
if (remote_commit) {
|
||||
log.console(`${mod}: remote commit = ${remote_commit}`)
|
||||
}
|
||||
} catch (e) {
|
||||
log.console(`${mod}: failed to check remote commit`)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if module exists in lock file
|
||||
if (!lock.modules[mod] || !lock.modules[mod].hash) {
|
||||
@@ -44,6 +60,11 @@ uses.download = function()
|
||||
} else if (!io.exists(cache_path)) {
|
||||
log.console(`${mod}: cache missing, will download`)
|
||||
need_download = true
|
||||
} else if (remote_commit && (!lock.modules[mod].commit || lock.modules[mod].commit !== remote_commit)) {
|
||||
log.console(`${mod}: remote has new commit`)
|
||||
log.console(` local: ${lock.modules[mod].commit || 'unknown'}`)
|
||||
log.console(` remote: ${remote_commit}`)
|
||||
need_download = true
|
||||
}
|
||||
|
||||
if (!need_download) {
|
||||
@@ -79,6 +100,12 @@ uses.download = function()
|
||||
url: mods[mod],
|
||||
downloaded: time.text()
|
||||
}
|
||||
|
||||
// Store commit hash if available
|
||||
if (remote_commit) {
|
||||
lock.modules[mod].commit = remote_commit
|
||||
}
|
||||
|
||||
log.console(`${mod}: hash = ${hash_b32}`)
|
||||
|
||||
// Save updated lock file
|
||||
@@ -91,9 +118,14 @@ uses.download = function()
|
||||
|
||||
log.console(`extracting ${mod} (${count} files)...`)
|
||||
|
||||
// Remove existing module directory if it exists (for clean updates)
|
||||
if (io.exists(module_path)) {
|
||||
log.console(`${mod}: removing old version...`)
|
||||
io.rmdir(module_path)
|
||||
}
|
||||
|
||||
// Create module directory
|
||||
if (!io.exists(module_path))
|
||||
io.mkdir(module_path)
|
||||
io.mkdir(module_path)
|
||||
|
||||
// Extract each file
|
||||
for (var i = 0; i < count; i++) {
|
||||
|
||||
@@ -109,6 +109,74 @@ Shop.add_dependency = function(alias, locator) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Get the API URL for checking remote git commits
|
||||
Shop.get_api_url = function(locator) {
|
||||
var parsed = Shop.parse_locator(locator)
|
||||
if (!parsed) return null
|
||||
|
||||
// Handle different git hosting patterns
|
||||
if (locator.startsWith('https://')) {
|
||||
// Remove https:// prefix for parsing
|
||||
var cleanLocator = locator.substring(8)
|
||||
var hostAndPath = cleanLocator.split('@')[0]
|
||||
var parts = hostAndPath.split('/')
|
||||
|
||||
// Gitea pattern: gitea.pockle.world/user/repo@branch
|
||||
if (hostAndPath.includes('gitea.')) {
|
||||
var host = parts[0]
|
||||
var user = parts[1]
|
||||
var repo = parts[2]
|
||||
return 'https://' + host + '/api/v1/repos/' + user + '/' + repo + '/branches/' + parsed.version
|
||||
}
|
||||
|
||||
// GitHub pattern: github.com/user/repo@tag or @branch
|
||||
if (hostAndPath.includes('github.com')) {
|
||||
var user = parts[1]
|
||||
var repo = parts[2]
|
||||
// Try branch first, then tag
|
||||
return 'https://api.github.com/repos/' + user + '/' + repo + '/branches/' + parsed.version
|
||||
}
|
||||
|
||||
// GitLab pattern: gitlab.com/user/repo@tag
|
||||
if (hostAndPath.includes('gitlab.')) {
|
||||
var user = parts[1]
|
||||
var repo = parts[2]
|
||||
var projectId = encodeURIComponent(user + '/' + repo)
|
||||
return 'https://' + parts[0] + '/api/v4/projects/' + projectId + '/repository/branches/' + parsed.version
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback - return null if no API pattern matches
|
||||
return null
|
||||
}
|
||||
|
||||
// Extract commit hash from API response
|
||||
Shop.extract_commit_hash = function(locator, response) {
|
||||
if (!response) return null
|
||||
|
||||
var data
|
||||
try {
|
||||
data = json.decode(response)
|
||||
} catch (e) {
|
||||
log.console("Failed to parse API response: " + e)
|
||||
return null
|
||||
}
|
||||
|
||||
// Handle different git hosting response formats
|
||||
if (locator.includes('gitea.')) {
|
||||
// Gitea: response.commit.id
|
||||
return data.commit && data.commit.id
|
||||
} else if (locator.includes('github.com')) {
|
||||
// GitHub: response.commit.sha
|
||||
return data.commit && data.commit.sha
|
||||
} else if (locator.includes('gitlab.')) {
|
||||
// GitLab: response.commit.id
|
||||
return data.commit && data.commit.id
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// Get the module directory for a given alias
|
||||
Shop.get_module_dir = function(alias) {
|
||||
var config = Shop.load_config()
|
||||
|
||||
@@ -1,51 +1,118 @@
|
||||
// cell update <alias> - Update a dependency to a new version
|
||||
// cell update [alias] - Check for updates and optionally install them
|
||||
|
||||
var io = use('io')
|
||||
var shop = use('shop')
|
||||
var http = use('http')
|
||||
var toml = use('toml')
|
||||
var json = use('json')
|
||||
var os = use('os')
|
||||
|
||||
if (args.length < 1) {
|
||||
log.console("Usage: cell update <alias> [new-version]")
|
||||
log.console("Example: cell update jj_mod v0.7.0")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
var alias = args[0]
|
||||
|
||||
if (!io.exists('.cell/shop.toml')) {
|
||||
log.error("No shop.toml found. Run 'cell init' first.")
|
||||
if (!io.exists('.cell/cell.toml')) {
|
||||
log.error("No cell.toml found. Run 'cell init' first.")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
var config = shop.load_config()
|
||||
if (!config || !config.dependencies || !config.dependencies[alias]) {
|
||||
log.error("Dependency '" + alias + "' not found")
|
||||
if (!config || !config.dependencies) {
|
||||
log.console("No dependencies to update")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
var current_version = config.dependencies[alias]
|
||||
log.console("Current version: " + current_version)
|
||||
// Load lock file
|
||||
var lock_path = '.cell/lock.toml'
|
||||
var lock = {}
|
||||
if (io.exists(lock_path)) {
|
||||
var lock_content = io.slurp(lock_path)
|
||||
lock = toml.decode(lock_content)
|
||||
}
|
||||
if (!lock.modules) lock.modules = {}
|
||||
|
||||
if (args.length > 1) {
|
||||
// Update to specific version
|
||||
var new_version = args[1]
|
||||
var updates_available = []
|
||||
|
||||
// Parse the current locator to keep the host/path
|
||||
var parsed = shop.parse_locator(current_version)
|
||||
if (parsed) {
|
||||
var new_locator = parsed.path + '@' + new_version
|
||||
config.dependencies[alias] = new_locator
|
||||
shop.save_config(config)
|
||||
|
||||
log.console("Updated " + alias + " to " + new_locator)
|
||||
log.console("Run 'cell get " + new_locator + "' to fetch the new version")
|
||||
// Check specific dependency or all
|
||||
var deps_to_check = {}
|
||||
if (args.length > 0) {
|
||||
var alias = args[0]
|
||||
if (!config.dependencies[alias]) {
|
||||
log.error("Dependency '" + alias + "' not found")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
deps_to_check[alias] = config.dependencies[alias]
|
||||
} else {
|
||||
// TODO: Check for latest version
|
||||
log.console("TODO: Check for latest version of " + alias)
|
||||
log.console("For now, specify version: cell update " + alias + " <version>")
|
||||
deps_to_check = config.dependencies
|
||||
}
|
||||
|
||||
// Check each dependency for updates
|
||||
for (var alias in deps_to_check) {
|
||||
var locator = deps_to_check[alias]
|
||||
log.console("Checking " + alias + " (" + locator + ")...")
|
||||
|
||||
// Get API URL to check commits
|
||||
var api_url = shop.get_api_url(locator)
|
||||
if (!api_url) {
|
||||
log.console(" Cannot check updates (no API support)")
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
log.console(api_url)
|
||||
var api_response = http.fetch(api_url)
|
||||
var remote_commit = shop.extract_commit_hash(locator, text(api_response))
|
||||
|
||||
if (!remote_commit) {
|
||||
log.console(" Failed to get remote commit")
|
||||
continue
|
||||
}
|
||||
|
||||
var local_commit = lock.modules[alias] && lock.modules[alias].commit
|
||||
|
||||
if (!local_commit) {
|
||||
log.console(" No local commit tracked")
|
||||
updates_available.push({
|
||||
alias: alias,
|
||||
locator: locator,
|
||||
local_commit: null,
|
||||
remote_commit: remote_commit
|
||||
})
|
||||
} else if (local_commit !== remote_commit) {
|
||||
log.console(" Update available!")
|
||||
log.console(" Local: " + local_commit.substring(0, 8))
|
||||
log.console(" Remote: " + remote_commit.substring(0, 8))
|
||||
updates_available.push({
|
||||
alias: alias,
|
||||
locator: locator,
|
||||
local_commit: local_commit,
|
||||
remote_commit: remote_commit
|
||||
})
|
||||
} else {
|
||||
log.console(" Up to date (" + local_commit.substring(0, 8) + ")")
|
||||
}
|
||||
} catch (e) {
|
||||
log.console(" Failed to check: " + e)
|
||||
}
|
||||
}
|
||||
|
||||
if (updates_available.length === 0) {
|
||||
log.console("\nAll dependencies are up to date!")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
log.console("\n" + updates_available.length + " update(s) available:")
|
||||
for (var i = 0; i < updates_available.length; i++) {
|
||||
var update = updates_available[i]
|
||||
log.console(" - " + update.alias)
|
||||
}
|
||||
|
||||
// If specific dependency was requested, auto-install
|
||||
if (args.length > 0 && updates_available.length > 0) {
|
||||
log.console("\nDownloading update...")
|
||||
os.system("cell mod download")
|
||||
} else if (updates_available.length > 0) {
|
||||
log.console("\nRun 'cell mod download' to install updates")
|
||||
}
|
||||
|
||||
$_.stop()
|
||||
@@ -1,25 +1,11 @@
|
||||
var http = use('http')
|
||||
var text = use('text')
|
||||
|
||||
// Test with a simpler endpoint first
|
||||
log.console("Testing httpbin.org chunked response...")
|
||||
try {
|
||||
var b = http.fetch("https://httpbin.org/stream/3")
|
||||
log.console(b.length)
|
||||
var text1 = text(b)
|
||||
log.console("httpbin response length:", text1.length)
|
||||
log.console("httpbin response:", text1)
|
||||
} catch (e) {
|
||||
log.console("httpbin error:", e)
|
||||
}
|
||||
|
||||
log.console("\nTesting dictionary.ink...")
|
||||
try {
|
||||
var b2 = http.fetch("https://dictionary.ink/find?word=theological")
|
||||
var b2 = http.fetch("https://gitea.pockle.world/api/v1/repos/john/prosperon/branches/master")
|
||||
log.console(b2.length)
|
||||
var text2 = text(b2)
|
||||
log.console("dictionary response length:", text2.length)
|
||||
log.console("dictionary first 500 chars:", text2.substring(0, 500))
|
||||
log.console(text(b2))
|
||||
} catch (e) {
|
||||
log.console("dictionary error:", e)
|
||||
}
|
||||
Reference in New Issue
Block a user