Files
cell/scripts/shop.cm

224 lines
5.6 KiB
Plaintext

// Module shop system for managing dependencies and mods
var io = use('io')
var toml = use('toml')
var json = use('json')
var Shop = {}
var shop_path = '.cell/cell.toml'
// Load cell.toml configuration
Shop.load_config = function() {
if (!io.exists(shop_path))
return null
var content = io.slurp(shop_path)
return toml.decode(content)
}
// Save cell.toml configuration
Shop.save_config = function(config) {
io.slurpwrite(shop_path, toml.encode(config))
}
// Initialize .cell directory structure
Shop.init = function() {
if (!io.exists('.cell')) {
io.mkdir('.cell')
}
if (!io.exists('.cell/modules')) {
io.mkdir('.cell/modules')
}
if (!io.exists('.cell/build')) {
io.mkdir('.cell/build')
}
if (!io.exists('.cell/patches')) {
io.mkdir('.cell/patches')
}
if (!io.exists('.cell/lock.toml')) {
io.slurpwrite('.cell/lock.toml', '# Lock file for module integrity\n')
}
return true
}
// Parse module locator (e.g., "git.world/jj/mod@v0.6.3")
Shop.parse_locator = function(locator) {
var parts = locator.split('@')
if (parts.length != 2) {
return null
}
return {
path: parts[0],
version: parts[1],
name: parts[0].split('/').pop()
}
}
// Convert module locator to download URL
Shop.get_download_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]
// Gitea pattern: gitea.pockle.world/user/repo@branch
if (hostAndPath.includes('gitea.')) {
return 'https://' + hostAndPath + '/archive/' + parsed.version + '.zip'
}
// GitHub pattern: github.com/user/repo@tag
if (hostAndPath.includes('github.com')) {
return 'https://' + hostAndPath + '/archive/refs/tags/' + parsed.version + '.zip'
}
// GitLab pattern: gitlab.com/user/repo@tag
if (hostAndPath.includes('gitlab.')) {
return 'https://' + hostAndPath + '/-/archive/' + parsed.version + '/' + parsed.name + '-' + parsed.version + '.zip'
}
}
// Fallback to original locator if no pattern matches
return locator
}
// Add a dependency
Shop.add_dependency = function(alias, locator) {
var config = Shop.load_config()
if (!config) {
log.error("No cell.toml found")
return false
}
if (!config.dependencies) {
config.dependencies = {}
}
config.dependencies[alias] = locator
Shop.save_config(config)
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()
if (!config || !config.dependencies || !config.dependencies[alias]) {
return null
}
var version = config.dependencies[alias]
var module_name = alias + '@' + version.split('@')[1]
// Check if replaced
if (config.replace && config.replace[version]) {
return config.replace[version]
}
return '.cell/modules/' + module_name
}
// Compile a module
Shop.compile_module = function(alias) {
var module_dir = Shop.get_module_dir(alias)
if (!module_dir) {
log.error("Module not found: " + alias)
return false
}
log.console("Would compile module: " + alias + " from " + module_dir)
return true
}
// Build all modules
Shop.build = function() {
var config = Shop.load_config()
if (!config || !config.dependencies) {
return true
}
for (var alias in config.dependencies) {
Shop.compile_module(alias)
}
return true
}
return Shop