ebuild-autogen/ebuild/cli.scm

325 lines
14 KiB
Scheme
Raw Normal View History

2025-06-30 16:15:39 +02:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; cli.scm
;; Copyright (C) 2025 Cor Legemaat <cor@cor.za.net>
;;
;; This file is part of ebuild-autogen: you can redistribute it and/or modify it
;; under the terms of the GNU Affero General Public License as published by the
;; Free Software Foundation, version 3 of the License.
;;
;; ebuild-autogen is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
;; more details.
;;
;; You should have received a copy of the GNU General Public License along with
;; ebuild-autogen. If not, see <https://www.gnu.org/licenses/>.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-module (ebuild cli)
#:use-module (ice-9 exceptions)
#:use-module (ice-9 format)
#:use-module (ice-9 pretty-print)
#:use-module (ice-9 receive)
#:use-module (srfi srfi-1)
#:use-module (dql dql)
#:use-module (ebuild defs)
#:use-module (ebuild repo)
#:use-module (ebuild gen)
#:use-module (ebuild version)
#:use-module (config)
#:use-module (config api)
#:use-module (config parser sexp))
(define config
;; Define our root configuration
(configuration
(name 'ebuild-autogen)
(keywords
(list
;; Switch to force writing non-eager configuration files
(switch
(name 'write) (default #f) (test boolean?) (character #f)
(synopsis "Write configuration file in local dir."))
(switch
(name 'verbosity) (default 3) (example "3")
(handler string->number) (test integer?)
(synopsis "The verbosity level."))
(switch
(name 'submodule-update) (default #false) (test boolean?)
(synopsis "Fetch update subtree source repo"))
(switch
(name 'pkg-clean) (default #false) (test boolean?)
(synopsis "Remove packages from repo that's not in autogen subtree."))
(switch
(name 'ebuild-clean) (default #false) (test boolean?)
(synopsis "Remove ebuilds no more active."))
(switch
(name 'cache-clean) (default #false) (test boolean?)
(synopsis "Remove files from cache no more needed in tree gen."))
(switch
(name 'remote-push) (default #false) (test boolean?)
(synopsis "Commit and push updated tree to remote."))
(switch
(name 'init-from) (default "") (test string?)
(example "https://www.cor.za.net/code/portage-overlay")
(synopsis "An url to initialize the repo from scratch"))
;;TODO figure out how to use non parameter options from the command
;; line instead of this.
(switch
(name 'base) (default "") (test string?)
(synopsis "Base folder different from working dir."))
;; A setting in the configuration file, if it exists.
(setting
(name 'github-token) (default "")
(handler identity) (test string?)
(synopsis "The github authentication token.")
(description "The github authentication token as a string for
authentication when pulling package updates from github."))
(setting
(name 'filecache-path)
(default (if (getenv "XDG_CACHE_HOME")
(getenv "XDG_CACHE_HOME")
(string-append (getenv "HOME")
"/.cache/ebuild-autogen")))
(example (string-append (getenv "HOME")
"/.cache/ebuild-autogen"))
(handler identity) (test string?)
(synopsis "Cache files path.")
(description "Full path to the folder where to store the file cache."))
(setting
(name 'tmp-path) (default "/tmp/ebuild-autogen/")
(example "/tmp/ebuild-autogen/")
(handler identity) (test string?)
(synopsis "Temporary files path.")
(description "Full path to the folder for the temporary files."))))
(synopsis "Auto generate Gentoo ebuild's")
(description "ebuild-autogen is a Guile scheme application to auto generate
gentoo ebuild package definitions from the \"autogen.scm\" specification for
the package from the subtree source residing in the autogen folder of the
git repository.")
(parser sexp-parser)
;; Specify where we want to install configuration files
(directory (list (if (getenv "XDG_CONFIG_HOME")
(path (given (getenv "XDG_CONFIG_HOME"))
(eager? #f))
(in-home ".config/" #:wait?))))
(version version-str)
(copyright (list 2025))
(license agpl3)
(author "Cor Legemaat")))
(define-public main
(lambda (cmd-line)
(let ((options (getopt-config-auto cmd-line config)))
(when (option-ref options 'write)
(options-write options))
;; Init repo from url if requested.
(if (not (string=? (option-ref options 'init-from) ""))
(repo-clone (option-ref options 'init-from)
(if (not (string=? (option-ref options 'base) ""))
(option-ref options 'base)
(getcwd))))
(let* ((folder (if (not (string=? (option-ref options 'base) ""))
(option-ref options 'base)
(getcwd)))
(repo (repo-root-for folder (option-ref options 'verbosity)))
(parms (list (cons 'repo repo)
(cons 'verbosity (option-ref options 'verbosity))
(cons 'cache-path (option-ref options
'filecache-path))
(cons 'tmp-path (option-ref options 'tmp-path)))))
;; Update the source repository if requested.
(if (option-ref options 'submodule-update)
(repo-update-src folder))
;; Add our repository to the load path.
(add-to-load-path (string-append repo "/autogen"))
;; Add optional parameters if exist.
(if (not (string-null? (option-ref options 'github-token)))
(set! parms
(assoc-set! parms
'github-token
(option-ref options 'github-token))))
(with-exception-handler
(lambda (exception)
(if (>= (option-ref options 'verbosity)
verbosity-warn)
(begin
(display "Failed to read the repo parameters with ")
(if (exception-with-message? exception)
(display
(simple-format
#f " exception-message: \"~a\""
(exception-message exception))))
(if (and (exception-with-message? exception)
(exception-with-irritants? exception))
(display " and"))
(if (exception-with-irritants? exception)
(display
(simple-format
#f " exception-irritants: \"~a\""
(exception-irritants exception))))
(newline)))
'())
(lambda ()
(let ((repo-mod (resolve-module `(repo-local settings))))
(if (module-variable repo-mod 'parms)
(set! parms (append parms
(module-ref repo-mod 'parms))))))
#:unwind? #t)
;; Update the repo definition files.
(cp-repo-file repo
""
"autogen"
"README-repo.org"
(option-ref options 'verbosity))
(cp-repo-file repo
""
"autogen"
"metadata"
(option-ref options 'verbosity))
(cp-repo-file repo
""
"autogen"
"profiles"
(option-ref options 'verbosity))
(cp-repo-file repo
""
"autogen"
"repositories.xml"
(option-ref options 'verbosity))
(cp-repo-file repo
""
"autogen/"
".gitignore-repo"
(option-ref options 'verbosity)
#:file-dst ".gitignore")
;; Preform ebuild generation.
(let ((pkg-list (build-pkg-list repo folder #t)))
(if (>= (option-ref options 'verbosity)
verbosity-warn)
(begin (display "package-list:") (newline)
(pretty-print pkg-list)))
(let ((cache-files-used
(append-map (lambda (pkg)
(let ((name (string->symbol (assoc-ref pkg 'name)))
(cat (string->symbol (assoc-ref pkg 'category))))
(if (>= (option-ref options 'verbosity)
verbosity-notice)
(begin (display "pkg:") (newline)
(pretty-print (append parms pkg))))
(with-exception-handler
(lambda (exception)
(if (>= (option-ref options 'verbosity)
verbosity-error)
(begin
(display "Failed to update the package ")
(display (assoc-ref pkg 'category))
(display "/")
(display (assoc-ref pkg 'name))
(display " with")
(if (exception-with-message? exception)
(display
(simple-format
#f " exception-message: \"~a\""
(exception-message exception))))
(if (and (exception-with-message? exception)
(exception-with-irritants? exception))
(display " and"))
(if (exception-with-irritants? exception)
(display
(simple-format
#f " exception-irritants: \"~a\""
(exception-irritants exception))))
(newline)))
'())
(lambda ()
(let* ((pkg-mod (resolve-module `(,cat ,name autogen)))
(pkg-parms (append parms pkg))
(distfiles-used '())
(pkgfiles-used
(if pkg-mod
(let ((releases
(if (module-variable pkg-mod 'get-releases)
((module-ref pkg-mod 'get-releases)
(append parms pkg))
'())))
(append
;; Setup the folder and links for the package.
(if (module-variable pkg-mod 'setup-package)
((module-ref pkg-mod 'setup-package)
pkg-parms)
(setup-pkg pkg-parms))
;; Generate the ebuilds.
(receive (pkg-files dist-files)
(if (module-variable pkg-mod 'generate-ebuilds)
((module-ref pkg-mod 'generate-ebuilds)
pkg-parms
releases)
(ebuild-gen pkg-parms
releases))
(set! distfiles-used
(append distfiles-used dist-files))
pkg-files)))
(setup-pkg pkg-parms))))
(if (option-ref options 'ebuild-clean)
(clean-files pkgfiles-used
(string-join (list repo
(assoc-ref pkg 'category)
(assoc-ref pkg 'name))
file-name-separator-string)
(option-ref options 'verbosity)))
(display "Done with package: ")
(display (assoc-ref pkg 'category))
(display "/")
(display (assoc-ref pkg 'name))
(newline)
distfiles-used))
#:unwind? (< 1 (length pkg-list)))))
pkg-list)))
;; Clean deprecated cache files if requested.
(if (>= (option-ref options 'verbosity)
verbosity-notice)
(begin (display "distfiles-used:") (newline)
(pretty-print cache-files-used)
(display "\"") (newline)))
(if (and (or (string=? folder repo)
(string=? folder
(string-join (list repo "autogen")
file-name-separator-string)))
(option-ref options 'cache-clean))
(clean-files cache-files-used
(option-ref options 'filecache-path)
(option-ref options 'verbosity))))
;; The extra folders in repo not in src.
(let ((repo-pkgs (build-pkg-list repo folder #f)))
(map (lambda (pkg)
(if (null? ((dql (filter (where (lambda (val)
(string=? val
(assoc-ref pkg 'category)))
'category)
(where (lambda (val)
(string=? val
(assoc-ref pkg 'name)))
'name)))
pkg-list))
(if (>= (option-ref options 'verbosity)
verbosity-warn)
(begin (display "Absolute pkg ")
(display (assoc-ref pkg 'category))
(display "/")
(display (assoc-ref pkg 'name))
(display " found.")
(newline)))))
repo-pkgs)))
;; Commit and push the updates to master if requested.
(if (option-ref options 'repo-push)
(repo-push-master))
(display "Completed successfully ...") (newline)))))