Bläddra i källkod

Add gitlab support in scripts/new.lua (#2136)

* Add gitlab suppor

* Refactor scripts/new.lua

This adds better extensibility for the future, if we want to add more
git providers.

Also, the code now looks more idiomatic and clean.

* refactor(new.lua): simplify options table formatting
refactor(new.lua): simplify get_gitlab_data function by removing unnecessary comments and returns
refactor(new.lua): simplify get_github_data function by removing unnecessary comments and returns
refactor(new.lua): simplify generate_package function by removing unnecessary comments and returns
The changes in this commit simplify the formatting of the options table and remove unnecessary comments and returns from the get_gitlab_data, get_github_data, and generate_package functions. These changes improve the readability and maintainability of the code.

refactor(new.lua): simplify build system detection and installation
feat(new.lua): add support for more build systems and dependencies
The build system detection and installation code has been simplified by using a table of build systems and their corresponding dependencies and installation functions. This allows for easier addition of new build systems and dependencies. The script now supports more build systems such as Meson and Bazel, and their respective dependencies.

* Update new.lua

* Update new.lua

* Update new.lua

---------

Co-authored-by: Pablo <[email protected]>
Co-authored-by: ruki <[email protected]>
Pablo Alessandro Santos Hugen 2 år sedan
förälder
incheckning
878da0d63a
1 ändrade filer med 180 tillägg och 102 borttagningar
  1. 180 102
      scripts/new.lua

+ 180 - 102
scripts/new.lua

@@ -1,6 +1,7 @@
 import("core.base.option")
 import("core.base.semver")
 import("core.base.json")
+import("core.base.hashset")
 import("lib.detect.find_tool")
 import("lib.detect.find_file")
 import("net.http")
@@ -11,174 +12,251 @@ local options = {
     {nil, "repo", "v", nil, "Set repository name.",
                             "e.g. ",
                             "  - github:xmake-io/xmake",
-                            "  - brew:zlib"}
+                            "  - gitlab:xmake-io/xmake"}
 }
 
-function _generate_package_from_github(reponame)
-    -- get repository info
-    local gh = assert(find_tool("gh"), "gh not found!")
-    local repoinfo = os.iorunv(gh.program, {"repo", "view", reponame, "--json",
-        "description,homepageUrl,licenseInfo,url,sshUrl,name,latestRelease"})
+-- function to get Gitlab data
+function get_gitlab_data(reponame)
+    local glab = assert(find_tool("glab"), "glab not found!")
+    local host = os.iorunv(glab.program, {"config", "get", "host"}):trim()
+    local graphql_query = 'query={ project(fullPath: "' .. reponame .. '") { description webUrl sshUrlToRepo name } }'
+    local repoinfo = os.iorunv(glab.program, {"api", "graphql", "-f", graphql_query})
+
+    local data = {}
     if repoinfo then
         repoinfo = json.decode(repoinfo)
+        if repoinfo.data and repoinfo.data.project then
+            -- extract required data and restructure it
+            local project_data = repoinfo.data.project
+            data = {
+                description = project_data.description,
+                homepageUrl = project_data.webUrl,
+                licenseInfo = "MIT", -- NOTE: Find a way to get the project license in gitlab
+                url = project_data.webUrl,
+                sshUrl = project_data.sshUrlToRepo,
+                name = project_data.name,
+            }
+            repoinfo.data.project = data
+        end
+    end
+    return {host = host, data = data}
+end
+
+local function get_github_data(reponame)
+    local gh = assert(find_tool("gh"), "gh not found!")
+    local host = "github.com"
+    local data = os.iorunv(gh.program, {
+        "repo",
+        "view",
+        reponame,
+        "--json",
+        "description,homepageUrl,licenseInfo,url,sshUrl,name,latestRelease",
+    })
+    if data then
+        data = json.decode(data)
     end
-    vprint(repoinfo)
+    return {data = data, host = host}
+end
+
+function generate_package(reponame, get_data)
+    local repo_data = get_data(reponame)
+    local data = repo_data.data
+    local host = repo_data.host
 
     -- generate package header
-    local packagename = assert(repoinfo.name, "package name not found!"):lower()
-    local packagefile = path.join("packages", packagename:sub(1, 1), packagename, "xmake.lua")
+    local packagename = assert(data.name, "package name not found!"):lower()
+    local packagefile = path.join("packages", string.sub(packagename, 1, 1), packagename, "xmake.lua")
     local file = io.open(packagefile, "w")
+
+    -- define package and homepage
     file:print('package("%s")', packagename)
-    local homepage = repoinfo.homepageUrl
-    if homepage == nil or homepage == "" then
-        homepage = repoinfo.url
-    end
+    local homepage = data.homepageUrl and data.homepageUrl ~= "" and data.homepageUrl or data.url
     if homepage then
         file:print('    set_homepage("%s")', homepage)
     end
-    local description = repoinfo.description or ("The " .. packagename .. " package")
+
+    local description = data.description or ("The " .. packagename .. " package")
     file:print('    set_description("%s")', description)
-    local licensekey = type(repoinfo.licenseInfo) == "table" and repoinfo.licenseInfo.key
-    if licensekey then
+
+    -- define license if available
+    if type(data.licenseInfo) == "table" and data.licenseInfo.key then
         local licenses = {
             ["apache-2.0"] = "Apache-2.0",
             ["lgpl-2.0"] = "LGPL-2.0",
             ["lgpl-2.1"] = "LGPL-2.1",
             zlib = "zlib",
-            mit = "MIT"
+            mit = "MIT",
         }
-        local license = licenses[licensekey]
+        local license = licenses[data.licenseInfo.key]
         if license then
             file:print('    set_license("%s")', license)
         end
     end
     file:print("")
 
-    -- generate package urls and versions
+    -- define package URLs and versions
     local repodir
-    local has_xmake
-    local has_cmake
-    local has_meson
-    local has_bazel
-    local has_autoconf
-    local need_autogen
-    local latest_release = repoinfo.latestRelease
+    local has_xmake, has_cmake, has_meson, has_bazel, has_autoconf, need_autogen
+    local latest_release = data.latestRelease
+
     if type(latest_release) == "table" then
-        local url = ("https://github.com/%s/archive/refs/tags/%s.tar.gz"):format(reponame, latest_release.tagName)
-        local giturl = ("https://github.com/%s.git"):format(reponame)
-        file:write('    add_urls("https://github.com/' .. reponame .. '/archive/refs/tags/$(version).tar.gz",\n')
-        file:print('             "%s")', giturl)
+        local url = string.format("https://%s/%s/archive/refs/tags/%s.tar.gz", host, reponame, latest_release.tagName)
+        local giturl = string.format("https://%s/%s.git", host, reponame)
         local tmpfile = os.tmpfile({ramdisk = false}) .. ".tar.gz"
         repodir = tmpfile .. ".dir"
+
+        file:write('    add_urls("https://' .. host .. '/' .. reponame .. '/-/archive/$(version).tar.gz",\n')
+        file:print('             "%s")\n', giturl)
+
         print("downloading %s", url)
         http.download(url, tmpfile)
+
         file:print('    add_versions("%s", "%s")', latest_release.tagName, hash.sha256(tmpfile))
         archive.extract(tmpfile, repodir)
         os.rm(tmpfile)
     else
-        local giturl = ("https://github.com/%s.git"):format(reponame)
-        repodir = os.tmpfile({ramdisk = false})
+        local giturl = string.format("git@%s:%s.git", host, reponame)
+        repodir = os.tmpfile({ ramdisk = false })
+
         file:print('    add_urls("%s")', giturl)
+
         print("downloading %s", giturl)
-        git.clone(giturl, {outputdir = repodir, depth = 1})
-        local commit = git.lastcommit({repodir = repodir})
-        local version = try{ function() return os.iorunv("git", {"log", "-1", "--date=format:%Y.%m.%d", "--format=%ad"}, {curdir = repodir}) end}
+        git.clone(giturl, { outputdir = repodir, depth = 1 })
+
+        local commit = git.lastcommit({ repodir = repodir })
+        local version = try {
+            function()
+                return os.iorunv("git", {
+                    "log",
+                    "-1",
+                    "--date=format:%Y.%m.%d",
+                    "--format=%ad",
+                }, { curdir = repodir })
+            end
+        }
         if version then
             file:print('    add_versions("%s", "%s")', version:trim(), commit)
         end
     end
 
+    local build_systems = {
+        ["xmake.lua"] = {
+            deps = {},
+            install = function(configs, package)
+                return [=[
+        io.writefile("xmake.lua", [[
+            add_rules("mode.release", "mode.debug")
+            target("%s")
+                set_kind("$(kind)")
+                add_files("src/*.c")
+                add_headerfiles("src/(*.h)")
+        ]])
+        if package:config("shared") then
+            configs.kind = "shared"
+        end
+        import("package.tools.xmake").install(package, configs)]=]
+            end,
+        },
+        ["CMakeLists.txt"] = {
+            deps = {"cmake"},
+            install = function(configs, package)
+                return [[
+        table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:is_debug() and "Debug" or "Release"))
+        table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
+        import("package.tools.cmake").install(package, configs)]]
+            end,
+        },
+        ["configure,configure.ac,autogen.sh"] = {
+            deps = {"autoconf", "automake", "libtool"},
+            install = function(configs, package)
+                return [[
+        table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))
+        if package:is_debug() then
+            table.insert(configs, "--enable-debug")
+        end
+        import("package.tools.autoconf").install(package, configs)]]
+            end,
+        },
+        ["meson.build"] = {
+            deps = {"meson", "ninja"},
+            install = function(configs, package)
+                return [[
+        table.insert(configs, "-Ddefault_library=" .. (package:config("shared") and "shared" or "static"))
+        import("package.tools.meson").install(package, configs)]]
+            end,
+        },
+        ["BUILD,BUILD.bazel"] = {
+            deps = {"bazel"},
+            install = function(configs, package)
+                return 'import("package.tools.bazel").install(package, configs)'
+            end,
+        }
+    }
+
     -- detect build system
+    local build_system = nil
     if repodir then
         local files = os.files(path.join(repodir, "*")) or {}
         table.join2(files, os.files(path.join(repodir, "*", "*")))
         for _, file in ipairs(files) do
             local filename = path.filename(file)
-            if filename == "xmake.lua" then
-                has_xmake = true
-            elseif filename == "CMakeLists.txt" then
-                has_cmake = true
-            elseif filename == "configure" then
-                has_autoconf = true
-            elseif filename == "autogen.sh" or filename == "configure.ac" then
-                need_autogen = true
-                has_autoconf = true
-            elseif filename == "meson.build" then
-                has_meson = true
-            elseif filename == "BUILD" or filename == "BUILD.bazel" then
-                has_bazel = true
+            for k, v in pairs(build_systems) do
+                local filenames = hashset.from(k:split(","))
+                if filenames:has(filename) then
+                    build_system = v
+                    break
+                end
             end
         end
         os.rm(repodir)
     end
+    if not build_system then
+        build_system = build_systems["xmake.lua"]
+    end
 
     -- add dependencies
-    if has_cmake then
-        file:print("")
-        file:print('    add_deps("cmake")')
-    elseif has_meson then
-        file:print("")
-        file:print('    add_deps("meson", "ninja")')
-    elseif need_autogen then
-        file:print("")
-        file:print('    add_deps("autoconf", "automake", "libtool")')
-    elseif has_bazel then
-        file:print("")
-        file:print('    add_deps("bazel")')
+    if build_system then
+        file:print('')
+        local deps = table.wrap(build_system.deps)
+        if deps and #deps > 0 then
+            file:print('    add_deps("' .. table.concat(deps, '", "') .. '")')
+        end
     end
 
     -- generate install scripts
-    file:print("")
-    file:print("    on_install(function (package)")
-    file:print("        local configs = {}")
-    if has_cmake then
-        file:print('        table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))')
-        file:print('        table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))')
-        file:print('        import("package.tools.cmake").install(package, configs)')
-    elseif has_autoconf then
-        file:print('        table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))')
-        file:print('        if package:debug() then')
-        file:print('            table.insert(configs, "--enable-debug")')
-        file:print('        end')
-        file:print('        import("package.tools.autoconf").install(package, configs)')
-    elseif has_meson then
-        file:print('        table.insert(configs, "-Ddefault_library=" .. (package:config("shared") and "shared" or "static"))')
-        file:print('        import("package.tools.meson").install(package, configs)')
-    elseif has_bazel then
-        file:print('        import("package.tools.bazel").install(package, configs)')
-    else
-        file:print('        io.writefile("xmake.lua", [[')
-        file:print('            add_rules("mode.release", "mode.debug")')
-        file:print('            target("%s")', packagename)
-        file:write('                set_kind("$(kind)")\n')
-        file:print('                add_files("src/*.c")')
-        file:print('                add_headerfiles("src/(*.h)")')
-        file:print('        ]])')
-        file:print('        if package:config("shared") then')
-        file:print('            configs.kind = "shared"')
-        file:print('        end')
-        file:print('        import("package.tools.xmake").install(package, configs)')
+    file:print('')
+    file:print('    on_install(function (package)')
+    file:print('        local configs = {}')
+    if build_system then
+        file:print(build_system.install(configs, package))
     end
-    file:print("    end)")
+    file:print('    end)')
 
     -- generate test scripts
-    file:print("")
-    file:print("    on_test(function (package)")
+    file:print('')
+    file:print('    on_test(function (package)')
     file:print('        assert(package:has_cfuncs("foo", {includes = "foo.h"}))')
-    file:print("    end)")
-
+    file:print('    end)')
     file:close()
+
     io.cat(packagefile)
     cprint("${bright}%s generated!", packagefile)
 end
 
 function main(...)
-    local opt = option.parse(table.pack(...), options, "New a package.", "",
-        "Usage: xmake l scripts/new.lua [options]")
-    local repo = opt.repo
-    if repo and repo:startswith("github:") then
-        _generate_package_from_github(repo:sub(8))
-    else
-        raise("we need set repository name first!")
+    local opt = option.parse(table.pack(...), options, "New a package.", "", "Usage: xmake l scripts/new.lua [options]")
+    local repo = assert(opt.repo, "repository name must be set!")
+    local reponame = repo:sub(8)
+
+    if repo:startswith("github:") then
+        generate_package(reponame, get_github_data)
+        return
+    end
+
+    if repo:startswith("gitlab:") then
+        generate_package(reponame, get_gitlab_data)
+        return
     end
+
+    raise("unsupported repository source. only 'github' and 'gitlab' are supported.")
 end