From 1646b529e171f1b5c69fe764a42076d6ac8b96db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Fri, 27 May 2016 23:03:12 +0200 Subject: [PATCH] Fixed all bugs 2 Removed everything for a new complete rewrite of love-release. See #40 for proposals. --- .travis.yml | 4 +- config.ld | 2 +- rockspecs/love-release-git-1.rockspec | 26 +++ rockspecs/love-release-scm-1.rockspec | 43 ---- spec/main_spec.lua | 7 - src/main.lua | 13 -- src/pipes/args.lua | 126 ----------- src/pipes/conf.lua | 78 ------- src/pipes/env.lua | 115 ---------- src/project.lua | 303 -------------------------- src/script.lua | 96 -------- src/scripts/debian.lua | 139 ------------ src/scripts/love.lua | 20 -- src/scripts/macosx.lua | 91 -------- src/scripts/windows.lua | 89 -------- src/utils.lua | 123 ----------- 16 files changed, 30 insertions(+), 1245 deletions(-) create mode 100644 rockspecs/love-release-git-1.rockspec delete mode 100644 rockspecs/love-release-scm-1.rockspec delete mode 100644 src/main.lua delete mode 100644 src/pipes/args.lua delete mode 100644 src/pipes/conf.lua delete mode 100644 src/pipes/env.lua delete mode 100644 src/project.lua delete mode 100644 src/script.lua delete mode 100644 src/scripts/debian.lua delete mode 100644 src/scripts/love.lua delete mode 100644 src/scripts/macosx.lua delete mode 100644 src/scripts/windows.lua delete mode 100644 src/utils.lua diff --git a/.travis.yml b/.travis.yml index c26d5a7..7878f8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,8 @@ sudo: false env: - LUA="lua=5.1" + - LUA="lua=5.2" + - LUA="lua=5.3" - LUA="luajit=2.0" - LUA="luajit=2.1" @@ -18,7 +20,7 @@ install: - luarocks install luacov-coveralls script: - - luacheck --std lua51+luajit src + - luacheck --std lua51+lua52+lua53+luajit src - luacheck --std busted spec - busted --verbose --coverage diff --git a/config.ld b/config.ld index 40e7a59..15aabb8 100644 --- a/config.ld +++ b/config.ld @@ -4,5 +4,5 @@ description = [[ love-release - a Lua script to make LÖVE games releases easier ]] readme = "README.md" -format = "discount" +format = "markdown" title = "love-release documentation" diff --git a/rockspecs/love-release-git-1.rockspec b/rockspecs/love-release-git-1.rockspec new file mode 100644 index 0000000..bb6a698 --- /dev/null +++ b/rockspecs/love-release-git-1.rockspec @@ -0,0 +1,26 @@ +package = "love-release" +version = "git-1" +source = { + url = "git://github.com/MisterDA/love-release", + branch = "love-release-3", +} +description = { + summary = "Make LÖVE games releases easier", + detailed = [[ +love-release make LÖVE games releases easier. +It automates LÖVE Game Distribution. +]], + license = "MIT", + homepage = "https://github.com/MisterDA/love-release", +} +dependencies = { +} +build = { + type = "builtin", + modules = { + }, + install = { + bin = { + }, + }, +} diff --git a/rockspecs/love-release-scm-1.rockspec b/rockspecs/love-release-scm-1.rockspec deleted file mode 100644 index cf46171..0000000 --- a/rockspecs/love-release-scm-1.rockspec +++ /dev/null @@ -1,43 +0,0 @@ -package = "love-release" -version = "scm-1" -source = { - url = "git://github.com/MisterDA/love-release.git", -} -description = { - summary = "Make LÖVE games releases easier", - detailed = [[ -love-release make LÖVE games releases easier. -It automates LÖVE Game Distribution. -]], - license = "MIT", - homepage = "https://github.com/MisterDA/love-release", -} -dependencies = { - "argparse", - "loadconf", - "lua ~> 5.1", - "luafilesystem", - "lua-zip", - "middleclass", - "semver", -} -build = { - type = "builtin", - modules = { - ["love-release.scripts.debian"] = "src/scripts/debian.lua", - ["love-release.scripts.love"] = "src/scripts/love.lua", - ["love-release.scripts.macosx"] = "src/scripts/macosx.lua", - ["love-release.scripts.windows"] = "src/scripts/windows.lua", - ["love-release.pipes.args"] = "src/pipes/args.lua", - ["love-release.pipes.conf"] = "src/pipes/conf.lua", - ["love-release.pipes.env"] = "src/pipes/env.lua", - ["love-release.project"] = "src/project.lua", - ["love-release.script"] = "src/script.lua", - ["love-release.utils"] = "src/utils.lua", - }, - install = { - bin = { - ["love-release"] = "src/main.lua" - }, - }, -} diff --git a/spec/main_spec.lua b/spec/main_spec.lua index 9b0d1bb..e69de29 100644 --- a/spec/main_spec.lua +++ b/spec/main_spec.lua @@ -1,7 +0,0 @@ -describe("love-release tests", function() - describe("should test something", function() - it("not right now", function() - assert.truthy("Sorry.") - end) - end) -end) diff --git a/src/main.lua b/src/main.lua deleted file mode 100644 index eb1b0a4..0000000 --- a/src/main.lua +++ /dev/null @@ -1,13 +0,0 @@ ---- love-release main. --- @script love-release - -local Args = require 'love-release.pipes.args' -local conf = require 'love-release.pipes.conf' -local env = require 'love-release.pipes.env' -local Project = require 'love-release.project' - -local p = Project:new() -local args = Args:new() -args(conf(env(args(p)))) - -return 0 diff --git a/src/pipes/args.lua b/src/pipes/args.lua deleted file mode 100644 index 5a8722e..0000000 --- a/src/pipes/args.lua +++ /dev/null @@ -1,126 +0,0 @@ ---- Gather informations from the CLI --- @module args --- @usage args(project) - -local argparse = require 'argparse' -local class = require 'middleclass' -local utils = require 'love-release.utils' - -local Args = class('Args') - - -Args.pre = true - -Args.args = nil - -function Args:initialize() - self.pre = Args.pre - - local parser = argparse() - :name "love-release" - :description "Makes LÖVE games releases easier !" - :epilog "For more info, see https://github.com/MisterDA/love-release" - - - parser:argument("release", "Project release directory.") - :args "?" - parser:argument("source", "Project source directory.") - :args "?" - - parser:flag("-D", "Debian package.") - :target "debian" - parser:flag("-M", "MacOS X application.") - :target "macosx" - parser:option("-W", "Windows executable.") - :target "windows" - :args "0-1" - :count "0-2" - :argname "32|64" - - parser:option("-a --author", "Author full name.") - parser:flag("-b", "Compile new or updated files to LuaJIT bytecode.") - :target("compile") - parser:option("-d --desc", "Project description.") - parser:option("-e --email", "Author email.") - parser:option("-l --love", "LÖVE version to use.") - :target("loveVersion") - parser:option("-p --package", "Package and command name.") - parser:option("-t --title", "Project title.") - parser:option("-u --url", "Project homepage url.") - parser:option("--uti", "Project Uniform Type Identifier.") - parser:option("-v", "Project version.") - :target("version") - - parser:flag("--version", "Show love-release version and exit.") - :target("love_release") - - self.args = parser:parse() -end - - -function Args:__call(project) - local out = utils.io.out - local args = self.args - - if self.pre then - if args.source then project:setProjectDirectory(args.source) end - if args.release then project:setReleaseDirectory(args.release) end - if args.love_release then - local show = require 'luarocks.show' - local _, version = show.pick_installed_rock("love-release") - out("love-release "..version.."\n") - os.exit(0) - end - self.pre = false - return project - end - - if args.author then project:setAuthor(args.author) end - if args.compile then project:setCompile(true) end - if args.desc then project:setDescription(args.desc) end - if args.email then project:setEmail(args.email) end - if args.loveVersion then - assert(utils.love.isSupported(args.loveVersion), - "ARGS: "..args.loveVersion.." is not supported.\n") - project:setLoveVersion(args.loveVersion) - end - if args.package then project:setPackage(args.package) end - if args.title then project:setTitle(args.title) end - if args.url then project:setHomepage(args.url) end - if args.uti then project:setIdentifier(args.uti) end - if args.version then project:setVersion(args.version) end - - if project.projectDirectory == project.releaseDirectory then - project:setReleaseDirectory(project.releaseDirectory.."/releases") - end - - print(project) - - local script - script = require 'love-release.scripts.love' - script(project) - if args.macosx then - script = require 'love-release.scripts.macosx' - script(project) - end - if #args.windows > 0 then - local win = args.windows - local win32 = win[1][1] == "32" or (win[2] and win[2][1] == "32") - local win64 = win[1][1] == "64" or (win[2] and win[2][1] == "64") - if not win32 and not win64 then - win32, win64 = true, true - end - script = require 'love-release.scripts.windows' - if win32 then script(project, 32) end - if win64 then script(project, 64) end - end - if args.debian then - script = require 'love-release.scripts.debian' - script(project) - end - - return project -end - - -return Args diff --git a/src/pipes/conf.lua b/src/pipes/conf.lua deleted file mode 100644 index 083bfee..0000000 --- a/src/pipes/conf.lua +++ /dev/null @@ -1,78 +0,0 @@ ---- Gather informations from the LÖVE conf.lua file. --- @module conf --- @usage conf(project) - -local fs = require 'luarocks.fs' -local loadconf = require 'loadconf' -local semver = require 'semver' - -local utils = require 'love-release.utils' - - -local pipe = {} - -function pipe.pipe(project) - local err = utils.io.err - - -- checks for a conf.lua file - fs.change_dir(project.projectDirectory) - if not fs.exists("conf.lua") then - err("CONF: No conf.lua provided.\n") - return project - end - local conf = assert(loadconf.parse_file("conf.lua")) - fs.pop_dir() - - local function setString(key, value) - if type(value) == "string" then - project["set"..key](project, value) - end - end - - local function setLoveVersion(v) - if type(v) == "string" and v ~= "" then - local version = semver(v) - if not utils.love.isSupported(version) then - local scriptLoveVersion = project.loveVersion - err("CONF: Your LÖVE conf version ("..v - .. ") is not supported by love-release ("..tostring(scriptLoveVersion) - .. ").\n") - if version > scriptLoveVersion then - err(" You should update love-release.\n") - elseif version < scriptLoveVersion then - err(" You should update your project.\n") - end - end - project:setLoveVersion(version) - end - end - - -- extract LÖVE standard fields - setString("Title", conf.title) - setString("Package", conf.package) - setLoveVersion(conf.version) - - -- extract love-release fields - local releases = conf.releases - if type(releases) == "table" then - setString("Title", releases.title) - setString("Package", releases.package) - setLoveVersion(releases.loveVersion) - setString("Version", releases.version) - setString("Author", releases.author) - setString("Email", releases.email) - setString("Description", releases.description) - setString("Homepage", releases.homepage) - setString("Identifier", releases.identifier) - setString("ReleaseDirectory", releases.releaseDirectory) - end - - return project -end - - -setmetatable(pipe, { - __call = function(_, project) return pipe.pipe(project) end, -}) - -return pipe diff --git a/src/pipes/env.lua b/src/pipes/env.lua deleted file mode 100644 index 8ee4a63..0000000 --- a/src/pipes/env.lua +++ /dev/null @@ -1,115 +0,0 @@ ---- Gather informations from the environment. --- @module env --- @usage env(project) - -local fs = require 'luarocks.fs' -local semver = require 'semver' -local utils = require 'love-release.utils' - -local pipe = {} - - ---- Gets the version of the installed LÖVE. --- @treturn semver LÖVE version. --- @local -local function getSystemLoveVersion() - local handle = io.popen('love --version') - local result = handle:read("*a") - handle:close() - local version = result:match('%d+%.%d+%.%d+') - if version then - return semver(version) - end -end - ---- Gets the latest LÖVE version from the web. --- @treturn semver LÖVE version. --- @local -local function getWebLoveVersion() - local releasesPath = utils.cache.."/releases.xml" - - local ok, err = fs.download("https://love2d.org/releases.xml", - releasesPath, - true) - if ok then - local releasesXml = io.open(releasesPath, "rb") - local version = releasesXml:read("*a"):match("(%d+%.%d+%.%d+)") - releasesXml:close() - return semver(version) - else - return nil, err - end -end - ---- Gets the latest LÖVE version from the script, the system and the web. --- @tparam semver script script version. --- @tparam semver system system version. --- @tparam semver web web version. --- @treturn semver the latest version. --- @local -local function getLatestLoveVersion(script, system, web) - local version = script - if system and system >= script then - version = system - end - if web and web > version then - version = web - end - return version -end - -function pipe.pipe(project) - local err = utils.io.err - - -- checks for a main.lua file - fs.change_dir(project.projectDirectory) - if not fs.exists("main.lua") then - err("ENV: No main.lua provided.\n") - os.exit(1) - end - fs.pop_dir() - - -- title - project:setTitle(project.projectDirectory:match("[^/]+$")) - - -- package - project:setPackage(project.title:gsub("%W", "-"):lower()) - - -- LÖVE version - - local systemLoveVersion = getSystemLoveVersion() - local webLoveVersion = getWebLoveVersion() - local scriptLoveVersion = utils.love.lastVersion() - local isSupported = utils.love.isSupported - - if systemLoveVersion and not isSupported(systemLoveVersion) then - err("ENV: Your LÖVE installed version (" .. tostring(systemLoveVersion) .. - ") is not supported by love-release (" .. tostring(scriptLoveVersion) .. - ").\n") - if systemLoveVersion > scriptLoveVersion then - err(" You should update love-release.\n") - elseif systemLoveVersion < scriptLoveVersion then - err(" You should update LÖVE.\n") - end - end - - if webLoveVersion and not isSupported(webLoveVersion) then - err("ENV: The upstream LÖVE version (" .. tostring(webLoveVersion) .. - ") is not supported by love-release (" .. tostring(scriptLoveVersion) .. - ").\n") - err(" You should update love-release.\n") - end - - project:setLoveVersion(getLatestLoveVersion(scriptLoveVersion, - systemLoveVersion, - webLoveVersion)) - - return project -end - - -setmetatable(pipe, { - __call = function(_, project) return pipe.pipe(project) end, -}) - -return pipe diff --git a/src/project.lua b/src/project.lua deleted file mode 100644 index 406e710..0000000 --- a/src/project.lua +++ /dev/null @@ -1,303 +0,0 @@ ---- Provides tools to manipulate a LÖVE project. --- @classmod project - -local fs = require 'luarocks.fs' -local lr_dir = require 'luarocks.dir' -local class = require 'middleclass' -local utils = require 'love-release.utils' - -local Project = class('Project') - - ---- Title of this project. -Project.title = nil - ---- Package name. It's the title converted to lowercase, with alpha-numerical --- characters and hyphens only. -Project.package = nil - ---- LÖVE version the project uses. -Project.loveVersion = nil - ---- Version. -Project.version = nil - ---- Author full name. -Project.author = nil - ---- Email. -Project.email = nil - ---- Description. -Project.description = nil - ---- Homepage URL. -Project.homepage = nil - ---- Uniform Type Identifier in reverse-DNS format. -Project.identifier = nil - ---- Project directory, where to find the game sources. -Project.projectDirectory = nil - ---- Project release directory, where to store the releases. -Project.releaseDirectory = nil - ---- True is the files should be precompiled to LuaJIT bytecode. -Project.compile = false - -Project._fileTree = nil -Project._fileList = nil - -function Project:initialize() - local defaultDirectory = fs.current_dir() - self:setProjectDirectory(defaultDirectory) - self:setReleaseDirectory(defaultDirectory) -end - ---- Recursive function used to build the tree. --- @local -local _buildFileTree -_buildFileTree = function(dir) - local subDir - for file in assert(fs.dir()) do - if not file:find("^%.git") then - if fs.is_dir(file) then - subDir = {} - dir[file] = subDir - assert(fs.change_dir(file)) - _buildFileTree(subDir, file) - assert(fs.pop_dir()) - elseif fs.is_file(file) then - dir[#dir+1] = file - end - end - end -end - ---- Constructs the file tree. --- @return File tree. The table represents the root directory. --- Sub-directories are represented as sub-tables, indexed by the directory name. --- Files are strings stored in each sub-tables. -function Project:fileTree() - if not self._fileTree then - assert(fs.change_dir(self.projectDirectory)) - self._fileTree = {} - _buildFileTree(self._fileTree) - assert(fs.pop_dir()) - end - return self._fileTree -end - ---- Recursive function used to build the file list. --- @local -local _buildFileList -_buildFileList = function(list, tree, dir) - for k, v in pairs(tree) do - if type(v) == "table" then - list[#list+1] = dir..k.."/" - _buildFileList(list, tree[k], dir..k.."/") - elseif type(v) == "string" then - list[#list+1] = dir..v - end - end -end - ---- Constructs the file list. --- @bool build Rebuild the file tree. --- @treturn table List of this project's files. -function Project:fileList(build) - if not self._fileList or build then - self._fileList = {} - _buildFileList(self._fileList, self:fileTree(), "") - self:excludeFiles() - end - return self._fileList -end - ---- Excludes files from the LÖVE file. --- @todo This function should be able to parse and use CVS files such as --- gitignore. It should also work on the file tree rather than on the file list. --- For now it works on the file list and only exludes the release directory if --- it is within the project directory. -function Project:excludeFiles() - local dir, rm_dir = self.releaseDirectory:gsub( - "^"..utils.lua.escape_string_regex(self.projectDirectory).."/", - "") - if rm_dir > 0 then - rm_dir = true - dir = "^"..dir - else - rm_dir = false - end - - if rm_dir then - local rm = false - local file - local n = #self._fileList - for i = 1, n do - file = self._fileList[i] - if rm_dir then if file:find(dir) then rm = true end end - if rm then - self._fileList[i] = nil - rm = false - end - end - end -end - ---[[ --- File tree traversal -local function deep(tree) - for k, v in pairs(tree) do - if type(v) == "string" then - print(v) - elseif type(v) == "table" then - print(k) - deep(v) - end - end -end -deep(t) ---]] - -local function escape(var) - if type(var) == "string" then - return "'"..var:gsub("'", "\'").."'" - else - return tostring(var) - end -end - ---- Prints debug informations. --- @local -function Project:__tostring() - return - '{\n'.. - ' title = '..escape(self.title)..',\n'.. - ' package = '..escape(self.package)..',\n'.. - ' loveVersion = \''..escape(self.loveVersion)..'\',\n'.. - ' version = '..escape(self.version)..',\n'.. - ' author = '..escape(self.author)..',\n'.. - ' email = '..escape(self.email)..',\n'.. - ' description = '..escape(self.description)..',\n'.. - ' homepage = '..escape(self.homepage)..',\n'.. - ' identifier = '..escape(self.identifier)..',\n'.. - ' compile = '..escape(self.compile)..',\n'.. - ' projectDirectory = '..escape(self.projectDirectory)..',\n'.. - ' releaseDirectory = '..escape(self.releaseDirectory)..',\n'.. - '}' -end - ---- Sets the title. --- @string title the title. --- @treturn project self. -function Project:setTitle(title) - self.title = title - return self -end - ---- Sets the package name. --- @string package the package name. --- @treturn project self. -function Project:setPackage(package) - self.package = package - return self -end - ---- Sets the LÖVE version used. --- @tparam semver version the LÖVE version. --- @treturn project self. -function Project:setLoveVersion(version) - self.loveVersion = version - return self -end - ---- Sets the project's version. --- @string version the version. --- @treturn project self. -function Project:setVersion(version) - self.version = version - return self -end - ---- Sets the author. --- @string author the author. --- @treturn project self. -function Project:setAuthor(author) - self.author = author - return self -end - ---- Sets the author's email. --- @string email the email. --- @treturn project self. -function Project:setEmail(email) - self.email = email - return self -end - ---- Sets the description. --- @string description the description. --- @treturn project self. -function Project:setDescription(description) - self.description = description - return self -end - ---- Sets the homepage. --- @string homepage the homepage. --- @treturn project self. -function Project:setHomepage(homepage) - self.homepage = homepage - return self -end - ---- Sets the identifier. --- @string identifier the identifier. --- @treturn project self. -function Project:setIdentifier(identifier) - self.identifier = identifier - return self -end - ---- Sets the source directory. The path is normalized and absoluted. --- @string directory the directory. --- @treturn project self. -function Project:setProjectDirectory(directory) - directory = fs.absolute_name(lr_dir.normalize(directory)) - assert(fs.change_dir(directory)) - fs.pop_dir() - self.projectDirectory = directory - return self -end - ---- Sets the release directory. The path is normalized and absoluted. --- @string directory the directory. --- @treturn project self. -function Project:setReleaseDirectory(directory) - directory = fs.absolute_name(lr_dir.normalize(directory)) - assert(fs.make_dir(directory)) - assert(fs.change_dir(directory)) - fs.pop_dir() - self.releaseDirectory = directory - return self -end - ---- Sets if Lua files should be precompiled to LuaJIT bytecode. By default they --- are not compiled. --- @bool value wether the files should be compiled or not. --- @treturn project self -function Project:setCompile(value) - if value then - if package.loaded.jit then - self.compile = true - else - assert(fs.is_tool_available("luajit", "LuaJIT", "-v")) - self.compile = true - end - end -end - - -return Project diff --git a/src/script.lua b/src/script.lua deleted file mode 100644 index 1a0ea6a..0000000 --- a/src/script.lua +++ /dev/null @@ -1,96 +0,0 @@ ---- A love-release script. --- @classmod script - -local fs = require 'luarocks.fs' -local class = require 'middleclass' -local lfs = require "lfs" -local zip = require 'brimworks.zip' -local utils = require 'love-release.utils' - -local Script = class('Script') - - ---- Current project. -Script.project = nil - ---- Name of the LÖVE file. -Script.loveFile = nil - -local function validate(project) - local valid, err = true, utils.io.err - if type(project.title) ~= "string" or project.title == "" then - err("SCRIPT: No title specified.\n") - valid = false - end - if type(project.package) ~= "string" or project.package == "" then - err("SCRIPT: No package specified.\n") - valid = false - end - if not type(project.loveVersion) then - err("SCRIPT: No LÖVE version specified.\n") - valid = false - end - if not valid then os.exit(1) end - return project -end - -function Script:initialize(project) - self.project = validate(project) - self.loveFile = project.title..'.love' -end - ---- Creates a LÖVE file in the release directory of the current project. -function Script:createLoveFile() - local ar = assert(zip.open(self.project.releaseDirectory.."/"..self.loveFile, - zip.OR(zip.CREATE, zip.CHECKCONS))) - - assert(fs.change_dir(self.project.projectDirectory)) - - local attributes, stat - for _, file in ipairs(self.project:fileList()) do - attributes = assert(lfs.attributes(file)) - stat = ar:stat(file) - - -- file is not present in the filesystem nor the archive - if not attributes and not stat then - utils.io.err("BUILD: "..file.." is not present in the file system.\n") - -- file is not present in the archive - elseif attributes and not stat then - utils.io.out("Add "..file.."\n") - if attributes.mode == "directory" then - ar:add_dir(file) - else - if self.project.compile then - ar:add(file, "string", utils.lua.bytecode(file)) - else - ar:add(file, "file", file) - end - end - -- file in the filesystem is more recent than in the archive - elseif attributes and stat and attributes.modification > stat.mtime + 5 then - if attributes.mode == "file" then - utils.io.out("Update "..file.."\n") - if self.project.compile then - ar:replace(assert(ar:name_locate(file)), "string", - utils.lua.bytecode(file)) - else - ar:replace(assert(ar:name_locate(file)), "file", file) - end - end - end - end - - for i = 1, #ar do - local file = ar:stat(i).name - -- file is present in the archive, but not in the filesystem - if not lfs.attributes(file) then - utils.io.out("Delete "..file.."\n") - ar:delete(i) - end - end - - ar:close() - assert(fs.pop_dir()) -end - -return Script diff --git a/src/scripts/debian.lua b/src/scripts/debian.lua deleted file mode 100644 index 24ddf8e..0000000 --- a/src/scripts/debian.lua +++ /dev/null @@ -1,139 +0,0 @@ ---- Debian package release. --- @module scripts.debian --- @usage debian(project) - -local fs = require 'luarocks.fs' -local dir = require 'luarocks.dir' -local lfs = require 'lfs' -local Script = require 'love-release.script' -local utils = require 'love-release.utils' - -local s = {} - - -local function validate(project) - local valid, err = true, utils.io.err - if type(project.author) ~= "string" or project.author == "" then - err("DEBIAN: No author specified.\n") - valid = false - end - if type(project.description) ~= "string" or project.description == "" then - err("DEBIAN: No description specified.\n") - valid = false - end - if type(project.email) ~= "string" or project.email == "" then - err("DEBIAN: No email specified.\n") - valid = false - end - if type(project.homepage) ~= "string" or project.homepage == "" then - err("DEBIAN: No homepage specified.\n") - valid = false - end - if type(project.version) ~= "string" or project.version == "" then - err("DEBIAN: No version specified.\n") - valid = false - end - if not valid then os.exit(1) end - return project -end - --- Is it such a good design to load the Debian package into memory with --- temporary files ? -function s.script(project) - local ok1, err1 = fs.is_tool_available("fakeroot", "fakeroot", "-v") - local ok2, err2 = fs.is_tool_available("dpkg-deb", "dpkg-deb") - if not ok1 or not ok2 then - if not ok1 then utils.io.err(err1) end - if not ok2 then utils.io.err(err2) end - os.exit(1) - end - - local script = Script:new(validate(project)) - script:createLoveFile() - - local tempDir = assert(fs.make_temp_dir("debian")) - local loveFileDeb = "/usr/share/games/"..project.package.."/"..script.loveFile - local loveFileRel = project.releaseDirectory.."/"..script.loveFile - local md5sums = {} - - local function writeFile(path, content, md5) - local fullPath = tempDir..path - assert(fs.make_dir(dir.dir_name(fullPath))) - local file = assert(io.open(fullPath, "wb")) - file:write(content) - file:close() - - if md5 then - md5sums[#md5sums+1] = { path = path, md5 = assert(fs.get_md5(fullPath)) } - end - end - - local function copyFile(orig, dest, md5) - local fullPath = tempDir..dest - assert(fs.make_dir(dir.dir_name(fullPath))) - assert(fs.copy(orig, fullPath)) - - if md5 then - md5sums[#md5sums+1] = { path = dest, md5 = assert(fs.get_md5(fullPath)) } - end - end - - -- /DEBIAN/control - writeFile("/DEBIAN/control", - "Package: "..project.package.."\n".. - "Version: "..project.version.."\n".. - "Architecture: all\n".. - "Maintainer: "..project.author.." <"..project.email..">\n".. - "Installed-Size: ".. - math.floor(assert(lfs.attributes(loveFileRel, "size")) / 1024).."\n".. - "Depends: love (>= "..tostring(project.loveVersion)..")\n".. - "Priority: extra\n".. - "Homepage: "..project.homepage.."\n".. - "Description: "..project.description.."\n" - ) - - -- /usr/share/applications/${PACKAGE}.desktop - writeFile("/usr/share/applications/"..project.package..".desktop", - "[Desktop Entry]\n".. - "Name="..project.title.."\n".. - "Comment="..project.description.."\n".. - "Exec="..project.package.."\n".. - "Type=Application\n".. - "Categories=Game;\n", - true - ) - - -- /usr/bin/${PACKAGE} - writeFile("/usr/bin/"..project.package, - "#!/bin/sh\n".. - "love '"..loveFileDeb:gsub("'", "\\'").."'\n", - true - ) - assert(fs.chmod(tempDir.."/usr/bin/"..project.package, "+x")) - - -- /usr/share/games/${PACKAGE}/${LOVE_FILE} - copyFile(project.releaseDirectory.."/"..script.loveFile, loveFileDeb, true) - - -- /DEBIAN/md5sums - local sum = "" - for _, v in ipairs(md5sums) do - sum = sum..v.md5.." "..v.path.."\n" - end - writeFile("/DEBIAN/md5sums", sum) - - -- create the package - local deb = project.releaseDirectory.."/"..project.package.."-".. - project.version.."_all.deb" - fs.delete(deb) - assert(fs.execute("fakeroot dpkg-deb -b ", tempDir, deb), - "DEBIAN: error while building the package.") - - fs.delete(tempDir) -end - - -setmetatable(s, { - __call = function(_, project) return s.script(project) end, -}) - -return s diff --git a/src/scripts/love.lua b/src/scripts/love.lua deleted file mode 100644 index 0426aa4..0000000 --- a/src/scripts/love.lua +++ /dev/null @@ -1,20 +0,0 @@ ---- LÖVE file release. --- @module scripts.love --- @usage love(project) - -local Script = require "love-release.script" - -local s = {} - - -function s.script(project) - local script = Script:new(project) - script:createLoveFile() -end - - -setmetatable(s, { - __call = function(_, project) return s.script(project) end, -}) - -return s diff --git a/src/scripts/macosx.lua b/src/scripts/macosx.lua deleted file mode 100644 index fba3233..0000000 --- a/src/scripts/macosx.lua +++ /dev/null @@ -1,91 +0,0 @@ ---- MacOS X app release. --- @module scripts.macosx --- @usage macosx(project) - -local fs = require "luarocks.fs" -local semver = require "semver" -local zip = require "brimworks.zip" -local Script = require "love-release.script" -local utils = require "love-release.utils" - -local s = {} - - -local function validate(project) - local valid, err = true, utils.io.err - if type(project.identifier) ~= "string" or project.identifier == "" then - err("MacOS X: No identifier specified.\n") - valid = false - end - if not valid then os.exit(1) end - return project -end - -function s.script(project) - local script = Script:new(validate(project)) - script:createLoveFile() - fs.change_dir(project.releaseDirectory) - - local prefix = "love-"..tostring(project.loveVersion).."-macosx-" - local bin - if project.loveVersion >= semver'0.9.0' then - bin = prefix.."x64.zip" - else - bin = prefix.."ub.zip" - end - local url = "https://bitbucket.org/rude/love/downloads/"..bin - local cache = utils.cache.."/"..bin - - -- Can't cache the archive because luarocks functions use a HEAD request to - -- Amazon AWS which will answer a 403. - -- assert(fs.download(url, cache, true)) - if not fs.exists(cache) then - assert(fs.download(url, cache)) - end - - fs.delete(bin) - assert(fs.copy(cache, bin)) - - -- local ar = assert(zip.open(bin, zip.OR(zip.CHECKCONS))) - local ar = zip.open(bin) - - local infoPlistIndex = assert(ar:name_locate("love.app/Contents/Info.plist")) - local infoPlistSize = assert(ar:stat(infoPlistIndex).size) - local infoPlistHandle = assert(ar:open(infoPlistIndex)) - local infoPlist = assert(infoPlistHandle:read(infoPlistSize)) - infoPlistHandle:close() - infoPlist = infoPlist - :gsub("\n\t<key>UTExportedTypeDeclarations</key>.*</array>", - "") - :gsub("(CFBundleIdentifier.-<string>)(.-)(</string>)", - "%1"..project.identifier.."%3") - :gsub("(CFBundleName.-<string>)(.-)(</string>)", - "%1"..project.title..".love%3") - - ar:add("love.app/Contents/Resources/"..script.loveFile, - "file", script.loveFile) - - local app = project.title..".app" - for i = 1, #ar do - ar:rename(i, ar:stat(i).name:gsub("^love%.app", app)) - end - - ar:close() - - -- for unknown reason, replacing the Info.plist content earlier would cause - -- random crashes - ar = zip.open(bin) - assert(ar:replace(infoPlistIndex, "string", infoPlist)) - ar:close() - - os.rename(bin, project.title.."-macosx.zip") - - fs.pop_dir() -end - - -setmetatable(s, { - __call = function(_, project) return s.script(project) end, -}) - -return s diff --git a/src/scripts/windows.lua b/src/scripts/windows.lua deleted file mode 100644 index c163c9a..0000000 --- a/src/scripts/windows.lua +++ /dev/null @@ -1,89 +0,0 @@ ---- Windows exe release. --- @module scripts.windows --- @usage windows(project) - -local fs = require "luarocks.fs" -local semver = require "semver" -local zip = require "brimworks.zip" -local Script = require "love-release.script" -local utils = require "love-release.utils" - -local s = {} - - -local function release(script, project, arch) - local prefix = "love-"..tostring(project.loveVersion).."-win" - local dir, bin - if project.loveVersion >= semver'0.9.0' then - bin = prefix..arch..".zip" - dir = prefix..arch.."/" - else - if arch == 32 then - bin = prefix.."-x86.zip" - dir = prefix.."-x86/" - elseif arch == 64 then - bin = prefix.."-x64.zip" - dir = prefix.."-x64/" - end - end - local url = "https://bitbucket.org/rude/love/downloads/"..bin - local cache = utils.cache.."/"..bin - - -- Can't cache the archive because luarocks functions use a HEAD request to - -- Amazon AWS which will answer a 403. - -- assert(fs.download(url, cache, true)) - if not fs.exists(cache) then - assert(fs.download(url, cache)) - end - - fs.delete(bin) - assert(fs.copy(cache, bin)) - - local gameHandle = assert(io.open(script.loveFile, "rb")) - local game = gameHandle:read("*a") - gameHandle:close() - - -- local ar = assert(zip.open(bin, zip.OR(zip.CHECKCONS))) - local ar = zip.open(bin) - - local exeHandle = assert(ar:open(dir.."love.exe")) - local exe = assert(exeHandle:read(assert(ar:stat(dir.."love.exe")).size)) - exeHandle:close() - - ar:add(dir..project.package..".exe", "string", exe..game) - ar:delete(dir.."love.exe") - - local stat - for i = 1, #ar do - stat = ar:stat(i) - if stat then - ar:rename(i, stat.name:gsub( - "^"..utils.lua.escape_string_regex(dir), - utils.lua.escape_string_regex(project.title).."-win"..arch.."/")) - end - end - - ar:close() - - os.rename(bin, project.title.."-win"..arch..".zip") -end - -function s.script(project, arch) - local script = Script:new(project) - script:createLoveFile() - fs.change_dir(project.releaseDirectory) - if arch == 32 then - release(script, project, 32) - end - if arch == 64 and project.loveVersion >= semver'0.8.0' then - release(script, project, 64) - end - fs.pop_dir() -end - - -setmetatable(s, { - __call = function(_, project, arch) return s.script(project, arch) end, -}) - -return s diff --git a/src/utils.lua b/src/utils.lua deleted file mode 100644 index abe7010..0000000 --- a/src/utils.lua +++ /dev/null @@ -1,123 +0,0 @@ ---- Provides utility functions and constants. --- @module utils - -local cfg = require 'luarocks.cfg' -local fs = require 'luarocks.fs' -local semver = require 'semver' - -local utils = {} - - ---[[ CACHE ]]-- - ---- Cache directory. -utils.cache = nil - -do - local cache - if cfg.platforms.windows then - cache = os.getenv("APPDATA") - else - cache = os.getenv("HOME").."/.cache" - end - cache = fs.absolute_name(cache.."/love-release") - assert(fs.make_dir(cache)) - utils.cache = cache -end - - ---[[ LÖVE VERSION ]]-- - -utils.love = {} - ---- All supported LÖVE versions. --- @local -utils.love.versionTable = { - semver'0.10.1', semver'0.10.0', - semver'0.9.2', semver'0.9.1', semver'0.9.0', - semver'0.8.0', - semver'0.7.2', semver'0.7.1', semver'0.7.0', - semver'0.6.2', semver'0.6.1', semver'0.6.0', ---[[ - semver'0.5.0', - semver'0.4.0', - semver'0.3.2', semver'0.3.1', semver'0.3.0', - semver'0.2.1', semver'0.2.0', - semver'0.1.1', ---]] -} - ---- Last script LÖVE version. -function utils.love.lastVersion() - return utils.love.versionTable[1] -end - ---- First supported LÖVE version. -function utils.love.minVersion() - return utils.love.versionTable[#utils.love.versionTable] -end - ---- Checks if a LÖVE version exists and is supported. --- @tparam semver version LÖVE version. --- @treturn bool true is the version is supported. -function utils.love.isSupported(version) - if version >= utils.love.minVersion() - and version <= utils.love.lastVersion() then - for _, v in ipairs(utils.love.versionTable) do - if version == v then - return true - end - end - end - return false -end - ---[[ LUA ]]-- - -utils.lua = {} - ---- Compiles a file to LuaJIT bytecode. --- @string file file path. --- @treturn string bytecode. -function utils.lua.bytecode(file) - if package.loaded.jit then - return string.dump(assert(loadfile(file)), true) - else - local handle = io.popen('luajit -b '..file..' -') - local result = handle:read("*a") - handle:close() - return result - end -end - ---- Escapes a string to use as a regex. --- @string string to escape. -function utils.lua.escape_string_regex(string) - -- ^$()%.[]*+-? - return string:gsub('%%', '%%%%'):gsub('^%^', '%%^'):gsub('%$$', '%%$') - :gsub('%(', '%%('):gsub('%)', '%%)'):gsub('%.', '%%.') - :gsub('%[', '%%['):gsub('%]', '%%]'):gsub('%*', '%%*') - :gsub('%+', '%%+'):gsub('%-', '%%-'):gsub('%?', '%%?') -end - - ---[[ IO ]]-- - -local stdout = io.output(io.stdout) -local stderr = io.output(io.stderr) -utils.io = {} - ---- Prints a message to stdout. --- @string string the message. -function utils.io.out(string) - stdout:write(string) -end - ---- Prints a message to stderr. --- @string string the message. -function utils.io.err(string) - stderr:write(string) -end - - -return utils