From 4369f6d3ca00a0a876d047c02656293cd98a8ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jani=20V=C3=A4limaa?= Date: Thu, 1 Oct 2020 19:39:00 +0300 Subject: rpm-spec-mode.el: update to version 0.16 --- NEWS | 2 + rpm-spec-mode.el | 958 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 533 insertions(+), 427 deletions(-) diff --git a/NEWS b/NEWS index 4c8eea0..4d48232 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +- rpm-spec-mode.el: update to version 0.16 + Version 2.57 - 23 June 2020, by Thierry Vignaud - %rename: o don't obsolete what is provided (mga#26801) diff --git a/rpm-spec-mode.el b/rpm-spec-mode.el index 9b2e946..ac9d797 100644 --- a/rpm-spec-mode.el +++ b/rpm-spec-mode.el @@ -1,11 +1,10 @@ ;;; rpm-spec-mode.el --- RPM spec file editing commands for Emacs/XEmacs +;; Copyright (C) 1997-2015 Stig Bjørlykke, -;; Copyright (C) 1997-2002 Stig Bjørlykke, - -;; Author: Stig Bjørlykke, +;; Author: Stig Bjørlykke, ;; Keywords: unix, languages -;; Version: 0.12 +;; Version: 0.16 ;; This file is part of XEmacs. @@ -21,8 +20,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -;; MA 02111-1307, USA. +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301 USA. ;;; Synched up with: not in GNU Emacs. @@ -34,12 +33,15 @@ ;; Tim Powers and Trond Eivind Glomsrød ;; for Red Hat adaptions and some fixes. ;; Chmouel Boudjnah for Mandrake fixes. +;; Ville Skyttä for some fixes. +;; Adam Spiers for GNU emacs compilation +;; and other misc fixes. ;;; ToDo: ;; - rewrite function names. ;; - autofill changelog entries. -;; - customize rpm-tags-list and rpm-group-tags-list. +;; - customize rpm-tags-list, rpm-obsolete-tags-list and rpm-group-tags-list. ;; - get values from `rpm --showrc'. ;; - ssh/rsh for compile. ;; - finish integrating the new navigation functions in with existing stuff. @@ -50,7 +52,7 @@ ;; This mode is used for editing spec files used for building RPM packages. ;; ;; Most recent version is available from: -;; +;; ;; ;; Put this in your .emacs file to enable autoloading of rpm-spec-mode, ;; and auto-recognition of ".spec" files: @@ -62,13 +64,11 @@ ;; ;;; Code: -(require 'cl) +(require 'compile) -(defconst rpm-spec-mode-version "0.12" "Version of `rpm-spec-mode'.") +(defconst rpm-spec-mode-version "0.16" "Version of `rpm-spec-mode'.") -;Fix for GNU/Emacs -(if (not(featurep 'xemacs)) - (fset 'define-obsolete-variable-alias 'make-obsolete)) +(eval-and-compile (defvar running-xemacs nil)) (defgroup rpm-spec nil "RPM spec mode with Emacs/XEmacs enhancements." @@ -76,7 +76,7 @@ :group 'languages) (defcustom rpm-spec-build-command "rpmbuild" - "Command for building a RPM package." + "Command for building an RPM package." :type 'string :group 'rpm-spec) @@ -92,11 +92,6 @@ in \"%build\" and \"%install\" stage." :type 'boolean :group 'rpm-spec) -(defcustom rpm-spec-no-deps nil - "Do not verify the dependencies." - :type 'boolean - :group 'rpm-spec) - (defcustom rpm-spec-timecheck "0" "Set the \"timecheck\" age (0 to disable). The timecheck value expresses, in seconds, the maximum age of a file @@ -106,7 +101,7 @@ timecheck age." :group 'rpm-spec) (defcustom rpm-spec-buildroot "" - "Override the BuildRoot tag with directory ." + "When building, override the BuildRoot tag with directory ." :type 'string :group 'rpm-spec) @@ -136,11 +131,20 @@ This is used during Tempo template completion." :type 'boolean :group 'rpm-spec) +(define-obsolete-variable-alias + 'rpm-spec-test 'rpm-spec-nobuild) + (defcustom rpm-spec-nobuild nil "Do not execute any build stages. Useful for testing out spec files." :type 'boolean :group 'rpm-spec) +(defcustom rpm-spec-quiet nil + "Print as little as possible. +Normally only error messages will be displayed." + :type 'boolean + :group 'rpm-spec) + (defcustom rpm-spec-sign-gpg nil "Embed a GPG signature in the package. This signature can be used to verify the integrity and the origin of @@ -153,11 +157,6 @@ the package." :type 'boolean :group 'rpm-spec) -(defcustom rpm-spec-old-rpm nil - "Set if using `rpm' as command for building packages." - :type 'boolean - :group 'rpm-spec) - (define-obsolete-variable-alias 'rpm-initialize-sections 'rpm-spec-initialize-sections) @@ -166,11 +165,6 @@ the package." :type 'boolean :group 'rpm-spec) -(defcustom rpm-spec-use-tabs nil - "Use tabs instead of a space to indent tags." - :type 'boolean - :group 'rpm-spec) - (define-obsolete-variable-alias 'rpm-insert-version 'rpm-spec-insert-changelog-version) @@ -179,11 +173,6 @@ the package." :type 'boolean :group 'rpm-spec) -(defcustom rpm-spec-insert-changelog-version-with-shell t - "Automatically add version with shell in a new change log entry." - :type 'boolean - :group 'rpm-spec) - (defcustom rpm-spec-user-full-name nil "*Full name of the user. This is used in the change log and the Packager tag. It defaults to the @@ -200,8 +189,50 @@ value returned by function `user-mail-address'." string) :group 'rpm-spec) +(defcustom rpm-spec-indent-heading-values nil + "*Indent values for all tags in the \"heading\" of the spec file." + :type 'boolean + :group 'rpm-spec) + +(defcustom rpm-spec-default-release "1" + "*Default value for the Release tag in new spec files." + :type 'string + :group 'rpm-spec) + +(defcustom rpm-spec-default-epoch nil + "*If non-nil, default value for the Epoch tag in new spec files." + :type '(choice (const :tag "No Epoch" nil) integer) + :group 'rpm-spec) + +(defcustom rpm-spec-default-buildroot + "%{_tmppath}/%{name}-%{version}-%{release}-root" + "*Default value for the BuildRoot tag in new spec files." + :type 'integer + :group 'rpm-spec) + +(defcustom rpm-spec-default-build-section "" + "*Default %build section in new spec files." + :type 'string + :group 'rpm-spec) + +(defcustom rpm-spec-default-install-section "rm -rf $RPM_BUILD_ROOT\n" + "*Default %install section in new spec files." + :type 'string + :group 'rpm-spec) + +(defcustom rpm-spec-default-clean-section "rm -rf $RPM_BUILD_ROOT\n" + "*Default %clean section in new spec files." + :type 'string + :group 'rpm-spec) + +(defcustom rpm-spec-auto-topdir nil + "*Automatically detect an rpm build directory tree and define _topdir." + :type 'boolean + :group 'rpm-spec) + (defgroup rpm-spec-faces nil "Font lock faces for `rpm-spec-mode'." + :prefix "rpm-spec-" :group 'rpm-spec :group 'faces) @@ -209,88 +240,105 @@ value returned by function `user-mail-address'." ;; variables used by navigation functions. (defconst rpm-sections - '("preamble" "description" "prep" "setup" "build" "install" "clean" + '("preamble" "description" "prep" "setup" "build" "install" "check" "clean" "changelog" "files") "Partial list of section names.") (defvar rpm-section-list '(("preamble") ("description") ("prep") ("setup") ("build") ("install") - ("clean") ("changelog") ("files")) + ("check") ("clean") ("changelog") ("files")) "Partial list of section names.") (defconst rpm-scripts '("pre" "post" "preun" "postun" - "trigger" "triggerin" "triggerun" "triggerpostun") + "trigger" "triggerin" "triggerprein" "triggerun" "triggerpostun" + "pretrans" "posttrans" "verifyscript") "List of rpm scripts.") (defconst rpm-section-seperate "^%\\(\\w+\\)\\s-") (defconst rpm-section-regexp (eval-when-compile (concat "^%" (regexp-opt - ;; From RPM 4.1 sources, file build/parseSpec.c: partList[]. - '("build" "changelog" "clean" "description" "files" "install" - "package" "post" "postun" "pre" "prep" "preun" "trigger" - "triggerin" "triggerpostun" "triggerun" "verifyscript") t) + ;; From RPM 4.12.0 sources, file build/parseSpec.c: partList[]. + '("package" "prep" "build" "install" "check" "clean" "preun" + "postun" "pretrans" "posttrans" "pre" "post" "files" "changelog" + "description" "triggerpostun" "triggerprein" "triggerun" + "triggerin" "trigger" "verifyscript" "sepolicy") t) "\\b")) "Regular expression to match beginning of a section.") ;;------------------------------------------------------------ (defface rpm-spec-tag-face - '(( ((class color) (background light)) (:foreground "blue") ) + '(( ((class color) (background light)) (:foreground "blue3") ) ( ((class color) (background dark)) (:foreground "blue") )) - "*The face used for tags." + "*Face for tags." + :group 'rpm-spec-faces) + +(defface rpm-spec-obsolete-tag-face + '(( ((class color)) (:foreground "white" :background "red") )) + "*Face for obsolete tags." :group 'rpm-spec-faces) (defface rpm-spec-macro-face '(( ((class color) (background light)) (:foreground "purple") ) ( ((class color) (background dark)) (:foreground "yellow") )) - "*The face used for macros." + "*Face for RPM macros and variables." :group 'rpm-spec-faces) (defface rpm-spec-var-face '(( ((class color) (background light)) (:foreground "maroon") ) ( ((class color) (background dark)) (:foreground "maroon") )) - "*The face used for environment variables." + "*Face for environment variables." :group 'rpm-spec-faces) (defface rpm-spec-doc-face - '(( ((class color) (background light)) (:foreground "magenta") ) + '(( ((class color) (background light)) (:foreground "magenta3") ) ( ((class color) (background dark)) (:foreground "magenta") )) - "*The face used for document files." + "*Face for %doc and %license entries in %files." :group 'rpm-spec-faces) (defface rpm-spec-dir-face - '(( ((class color) (background light)) (:foreground "green") ) + '(( ((class color) (background light)) (:foreground "green4") ) ( ((class color) (background dark)) (:foreground "green") )) - "*The face used for directories." + "*Face for %dir entries in %files." :group 'rpm-spec-faces) (defface rpm-spec-package-face - '(( ((class color) (background light)) (:foreground "red") ) + '(( ((class color) (background light)) (:foreground "red3") ) ( ((class color) (background dark)) (:foreground "red") )) - "*The face used for files." + "*Face for package tag." :group 'rpm-spec-faces) (defface rpm-spec-ghost-face - '(( ((class color) (background light)) (:foreground "red") ) + '(( ((class color) (background light)) (:foreground "gray50") ) ( ((class color) (background dark)) (:foreground "red") )) - "*The face used for ghost tags." + "*Face for %ghost and %config entries in %files." + :group 'rpm-spec-faces) + +(defface rpm-spec-section-face + '(( ((class color) (background light)) (:foreground "purple" :underline t) ) + ( ((class color) (background dark)) (:foreground "yellow" :underline t) )) + "*Face for section markers." :group 'rpm-spec-faces) ;;; GNU emacs font-lock needs these... (defvar rpm-spec-macro-face - 'rpm-spec-macro-face "*Face for macros.") + 'rpm-spec-macro-face "*Face for RPM macros and variables.") (defvar rpm-spec-var-face 'rpm-spec-var-face "*Face for environment variables.") (defvar rpm-spec-tag-face 'rpm-spec-tag-face "*Face for tags.") +(defvar rpm-spec-obsolete-tag-face + 'rpm-spec-tag-face "*Face for obsolete tags.") (defvar rpm-spec-package-face 'rpm-spec-package-face "*Face for package tag.") (defvar rpm-spec-dir-face - 'rpm-spec-dir-face "*Face for directory entries.") + 'rpm-spec-dir-face "*Face for %dir entries in %files.") (defvar rpm-spec-doc-face - 'rpm-spec-doc-face "*Face for documentation entries.") + 'rpm-spec-doc-face "*Face for %doc and %license entries in %files.") (defvar rpm-spec-ghost-face - 'rpm-spec-ghost-face "*Face for \"%ghost\" files.") + 'rpm-spec-ghost-face "*Face for %ghost and %config entries in %files.") +(defvar rpm-spec-section-face + 'rpm-spec-section-face "*Face for section markers.") (defvar rpm-default-umask "-" "*Default umask for files, specified with \"%attr\".") @@ -302,157 +350,127 @@ value returned by function `user-mail-address'." ;;------------------------------------------------------------ (defvar rpm-no-gpg nil "Tell rpm not to sign package.") +(defvar rpm-spec-nobuild-option "--nobuild" "Option for no build.") (defvar rpm-tags-list - ;; From RPM 4.1 sources, file build/parsePreamble.c: preambleList[].") - '(("AutoProv") - ("AutoReq") - ("AutoReqProv") - ("BuildArch") - ("BuildArchitectures") - ("BuildConflicts") - ("BuildPreReq") - ("BuildRequires") - ("BuildRoot") - ("Conflicts") + ;; From RPM 4.12.0 sources, file build/parsePreamble.c: preambleList[]: + '(("Name") + ("Version") + ("Release") + ("Epoch") + ("Summary") ("License") - ("%description") ("Distribution") ("DistURL") - ("DocDir") - ("Epoch") + ("Vendor") + ("Group") + ("Packager") + ("URL") + ("VCS") + ("Source") + ("Patch") + ("NoSource") + ("NoPatch") ("ExcludeArch") - ("ExcludeOS") ("ExclusiveArch") + ("ExcludeOS") ("ExclusiveOS") - ("%files") - ("Group") ("Icon") - ("%ifarch") - ("License") - ("Name") - ("NoPatch") - ("NoSource") - ("Obsoletes") - ("%package") - ("Packager") - ("Patch") - ("Prefix") - ("Prefixes") - ("PreReq") ("Provides") - ("Release") ("Requires") - ("RHNPlatform") - ("Serial") - ("Source") - ("Summary") - ("URL") - ("Vendor") - ("Version")) + ("Recommends") + ("Suggests") + ("Supplements") + ("Enhances") + ("PreReq") + ("Conflicts") + ("Obsoletes") + ("Prefixes") + ("Prefix") + ("BuildRoot") + ("BuildArchitectures") + ("BuildArch") + ("BuildConflicts") + ("BuildPreReq") + ("BuildRequires") + ("AutoReqProv") + ("AutoReq") + ("AutoProv") + ("DocDir") + ("DistTag") + ("BugURL") + ("OrderWithRequires") + ;; ...plus some from rpm5.org: + ("CVSId") + ("SVNId") + ("BuildSuggests") + ("BuildEnhances") + ("Variants") + ("Variant") + ("XMajor") + ("XMinor") + ("RepoTag") + ("Keywords") + ("Keyword") + ("BuildPlatforms") + ;; ...plus a few macros that aren't tags but useful here. + ("%description") + ("%files") + ("%ifarch") + ("%package") + ) "List of elements that are valid tags.") -;; echo "(defvar rpm-group-tags-list" -;; echo " ;; Auto generated from Mageia GROUPS file" -;; printf "\t%s\n" "'(" -;; cat /usr/share/doc/*/GROUPS | while read i; do -;; printf "\t %s%s%s\n" '("' "$i" '")' -;; done -;; printf "\t%s\n\t%s" ")" '"List of elements that are valid group tags.")' +(defvar rpm-tags-regexp + (concat "\\(\\<" (regexp-opt (mapcar 'car rpm-tags-list)) + "\\|\\(Patch\\|Source\\)[0-9]+\\>\\)") + "Regular expression for matching valid tags.") + +(defvar rpm-obsolete-tags-list + ;; From RPM sources, file build/parsePreamble.c: preambleList[]. + '(("Copyright") ;; 4.4.2 + ("RHNPlatform") ;; 4.4.2, 4.4.9 + ("Serial") ;; 4.4.2, 4.4.9 + ) + "List of elements that are obsolete tags in some versions of rpm.") + +(defvar rpm-obsolete-tags-regexp + (regexp-opt (mapcar 'car rpm-obsolete-tags-list) 'words) + "Regular expression for matching obsolete tags.") (defvar rpm-group-tags-list - ;; Auto generated from Mageia GROUPS file - '( - ("Accessibility") - ("Archiving/Backup") - ("Archiving/Cd burning") - ("Archiving/Compression") - ("Archiving/Other") - ("Books/Computer books") - ("Books/Faqs") - ("Books/Howtos") - ("Books/Literature") - ("Books/Other") - ("Communications") - ("Databases") - ("Development/C") - ("Development/C++") - ("Development/Databases") - ("Development/GNOME and GTK+") - ("Development/Java") - ("Development/KDE and Qt") - ("Development/Kernel") - ("Development/Other") - ("Development/Perl") - ("Development/PHP") - ("Development/Python") - ("Development/Ruby") - ("Editors") - ("Education") - ("Emulators") - ("File tools") - ("Games/Adventure") - ("Games/Arcade") - ("Games/Boards") - ("Games/Cards") - ("Games/Other") - ("Games/Puzzles") - ("Games/Sports") - ("Games/Strategy") - ("Graphical desktop/Enlightenment") - ("Graphical desktop/FVWM based") - ("Graphical desktop/GNOME") - ("Graphical desktop/Icewm") - ("Graphical desktop/KDE") - ("Graphical desktop/Other") - ("Graphical desktop/Sawfish") - ("Graphical desktop/WindowMaker") - ("Graphical desktop/Xfce") - ("Graphics") - ("Monitoring") - ("Networking/Chat") - ("Networking/File transfer") - ("Networking/IRC") - ("Networking/Instant messaging") - ("Networking/Mail") - ("Networking/News") - ("Networking/Other") - ("Networking/Remote access") - ("Networking/WWW") - ("Office") - ("Publishing") - ("Sciences/Astronomy") - ("Sciences/Biology") - ("Sciences/Chemistry") - ("Sciences/Computer science") - ("Sciences/Geosciences") - ("Sciences/Mathematics") - ("Sciences/Other") - ("Sciences/Physics") - ("Shells") - ("Sound") - ("System/Base") - ("System/Configuration/Boot and Init") - ("System/Configuration/Hardware") - ("System/Configuration/Networking") - ("System/Configuration/Other") - ("System/Configuration/Packaging") - ("System/Configuration/Printing") - ("System/Fonts/Console") - ("System/Fonts/True type") - ("System/Fonts/Type1") - ("System/Fonts/X11 bitmap") - ("System/Internationalization") - ("System/Kernel and hardware") - ("System/Libraries") - ("System/Servers") - ("System/X11") - ("Terminals") - ("Text tools") - ("Toys") - ("Video") - ) - "List of elements that are valid group tags.") + ;; From RPM 4.4.9 sources, file GROUPS. + '(("Amusements/Games") + ("Amusements/Graphics") + ("Applications/Archiving") + ("Applications/Communications") + ("Applications/Databases") + ("Applications/Editors") + ("Applications/Emulators") + ("Applications/Engineering") + ("Applications/File") + ("Applications/Internet") + ("Applications/Multimedia") + ("Applications/Productivity") + ("Applications/Publishing") + ("Applications/System") + ("Applications/Text") + ("Development/Debuggers") + ("Development/Languages") + ("Development/Libraries") + ("Development/System") + ("Development/Tools") + ("Documentation") + ("System Environment/Base") + ("System Environment/Daemons") + ("System Environment/Kernel") + ("System Environment/Libraries") + ("System Environment/Shells") + ("User Interface/Desktops") + ("User Interface/X") + ("User Interface/X Hardware Support") + ) + "List of elements that are valid group tags.") (defvar rpm-spec-mode-syntax-table nil "Syntax table in use in `rpm-spec-mode' buffers.") @@ -474,6 +492,8 @@ value returned by function `user-mail-address'." (modify-syntax-entry ?| "." rpm-spec-mode-syntax-table) (modify-syntax-entry ?\' "." rpm-spec-mode-syntax-table)) +(eval-when-compile (or running-xemacs (defun set-keymap-name (a b)))) + (defvar rpm-spec-mode-map nil "Keymap used in `rpm-spec-mode'.") (unless rpm-spec-mode-map @@ -482,6 +502,7 @@ value returned by function `user-mail-address'." (set-keymap-name rpm-spec-mode-map 'rpm-spec-mode-map)) (define-key rpm-spec-mode-map "\C-c\C-c" 'rpm-change-tag) (define-key rpm-spec-mode-map "\C-c\C-e" 'rpm-add-change-log-entry) + (define-key rpm-spec-mode-map "\C-c\C-w" 'rpm-goto-add-change-log-entry) (define-key rpm-spec-mode-map "\C-c\C-i" 'rpm-insert-tag) (define-key rpm-spec-mode-map "\C-c\C-n" 'rpm-forward-section) (define-key rpm-spec-mode-map "\C-c\C-o" 'rpm-goto-section) @@ -510,10 +531,10 @@ value returned by function `user-mail-address'." (define-key rpm-spec-mode-map "\C-c\C-xi" 'rpm-change-timecheck-option) (define-key rpm-spec-mode-map "\C-c\C-xn" 'rpm-toggle-nobuild) (define-key rpm-spec-mode-map "\C-c\C-xo" 'rpm-files-owner) - (define-key rpm-spec-mode-map "\C-c\C-xp" 'rpm-change-target-option) (define-key rpm-spec-mode-map "\C-c\C-xr" 'rpm-toggle-rmsource) - (define-key rpm-spec-mode-map "\C-cxd" 'rpm-toggle-no-deps) + (define-key rpm-spec-mode-map "\C-c\C-xq" 'rpm-toggle-quiet) (define-key rpm-spec-mode-map "\C-c\C-xs" 'rpm-toggle-short-circuit) + (define-key rpm-spec-mode-map "\C-c\C-xt" 'rpm-change-target-option) (define-key rpm-spec-mode-map "\C-c\C-xu" 'rpm-files-umask) ;;(define-key rpm-spec-mode-map "\C-q" 'indent-spec-exp) ;;(define-key rpm-spec-mode-map "\t" 'sh-indent-line) @@ -550,14 +571,14 @@ value returned by function `user-mail-address'." ("Build Options" ["Short circuit" rpm-toggle-short-circuit :style toggle :selected rpm-spec-short-circuit] - ["No deps" rpm-toggle-no-deps - :style toggle :selected rpm-spec-no-deps] ["Remove source" rpm-toggle-rmsource :style toggle :selected rpm-spec-rmsource] ["Clean" rpm-toggle-clean :style toggle :selected rpm-spec-clean] ["No build" rpm-toggle-nobuild :style toggle :selected rpm-spec-nobuild] + ["Quiet" rpm-toggle-quiet + :style toggle :selected rpm-spec-quiet] ["GPG sign" rpm-toggle-sign-gpg :style toggle :selected rpm-spec-sign-gpg] ["Ignore dependencies" rpm-toggle-nodeps @@ -580,33 +601,41 @@ value returned by function `user-mail-address'." ))) (defvar rpm-spec-font-lock-keywords - '( - ("%[a-zA-Z0-9-_]+" 0 rpm-spec-macro-face) - ("^\\([a-zA-Z0-9]+\\)\\(\([a-zA-Z0-9,]+\)\\):" - (1 rpm-spec-tag-face) - (2 rpm-spec-ghost-face)) - ("^\\([a-zA-Z0-9]+\\):" 1 rpm-spec-tag-face) - ("%\\(de\\(fine\\|scription\\)\\|files\\|package\\)[ \t]+\\([^-][^ \t\n]*\\)" + (list + (cons rpm-section-regexp rpm-spec-section-face) + '("%[a-zA-Z0-9_]+" 0 rpm-spec-macro-face) + (cons (concat "^" rpm-obsolete-tags-regexp "\\(\([a-zA-Z0-9,_]+\)\\)[ \t]*:") + '((1 'rpm-spec-obsolete-tag-face) + (2 'rpm-spec-ghost-face))) + (cons (concat "^" rpm-tags-regexp "\\(\([a-zA-Z0-9,_]+\)\\)[ \t]*:") + '((1 'rpm-spec-tag-face) + (3 'rpm-spec-ghost-face))) + (cons (concat "^" rpm-obsolete-tags-regexp "[ \t]*:") + '(1 'rpm-spec-obsolete-tag-face)) + (cons (concat "^" rpm-tags-regexp "[ \t]*:") + '(1 'rpm-spec-tag-face)) + '("%\\(de\\(fine\\|scription\\)\\|files\\|global\\|package\\)[ \t]+\\([^-][^ \t\n]*\\)" (3 rpm-spec-package-face)) - ("%p\\(ost\\|re\\)\\(un\\)?[ \t]+\\([^-][^ \t\n]*\\)" + '("^%p\\(ost\\|re\\)\\(un\\|trans\\)?[ \t]+\\([^-][^ \t\n]*\\)" (3 rpm-spec-package-face)) - ("%configure " 0 rpm-spec-macro-face) - ("%dir[ \t]+\\([^ \t\n]+\\)[ \t]*" 1 rpm-spec-dir-face) - ("%doc\\(dir\\)?[ \t]+\\(.*\\)\n" 2 rpm-spec-doc-face) - ("%\\(ghost\\|config\\)[ \t]+\\(.*\\)\n" 2 rpm-spec-ghost-face) - ("^%.+-[a-zA-Z][ \t]+\\([a-zA-Z0-9\.-]+\\)" 1 rpm-spec-doc-face) - ("^\\(.+\\)(\\([a-zA-Z]\\{2,2\\}\\)):" + '("%configure " 0 rpm-spec-macro-face) + '("%dir[ \t]+\\([^ \t\n]+\\)[ \t]*" 1 rpm-spec-dir-face) + '("%\\(doc\\(dir\\)?\\|license\\)[ \t]+\\(.*\\)\n" 3 rpm-spec-doc-face) + '("%\\(ghost\\|config\\([ \t]*(.*)\\)?\\)[ \t]+\\(.*\\)\n" + 3 rpm-spec-ghost-face) + '("^%.+-[a-zA-Z][ \t]+\\([a-zA-Z0-9\.-]+\\)" 1 rpm-spec-doc-face) + '("^\\(.+\\)(\\([a-zA-Z]\\{2,2\\}\\)):" (1 rpm-spec-tag-face) (2 rpm-spec-doc-face)) - ("^\\*\\(.*[0-9] \\)\\(.*\\)\\(<.*>\\)\\(.*\\)\n" + '("^\\*\\(.*[0-9] \\)\\(.*\\)<\\(.*\\)>\\(.*\\)\n" (1 rpm-spec-dir-face) (2 rpm-spec-package-face) (3 rpm-spec-tag-face) - (4 font-lock-warning-face)) - ("%{[^{}]*}" 0 rpm-spec-macro-face) - ("$[a-zA-Z0-9_]+" 0 rpm-spec-var-face) - ("${[a-zA-Z0-9_]+}" 0 rpm-spec-var-face) - ) + (4 rpm-spec-ghost-face)) + '("%{[^{}]*}" 0 rpm-spec-macro-face) + '("$[a-zA-Z0-9_]+" 0 rpm-spec-var-face) + '("${[a-zA-Z0-9_]+}" 0 rpm-spec-var-face) + ) "Additional expressions to highlight in `rpm-spec-mode'.") ;;Initialize font lock for xemacs @@ -618,6 +647,8 @@ value returned by function `user-mail-address'." ;;------------------------------------------------------------ +(add-hook 'rpm-spec-mode-new-file-hook 'rpm-spec-initialize) + ;;;###autoload (defun rpm-spec-mode () "Major mode for editing RPM spec files. @@ -645,13 +676,13 @@ with no args, if that value is non-nil." "Post menu for `rpm-spec-mode'." rpm-spec-mode-menu) (easy-menu-add rpm-spec-mode-menu) - (if (= (buffer-size) 0) - (rpm-spec-initialize)) + (if (and (= (buffer-size) 0) rpm-spec-initialize-sections) + (run-hooks 'rpm-spec-mode-new-file-hook)) - (if (executable-find "rpmbuild") - (setq rpm-spec-build-command "rpmbuild") - (setq rpm-spec-old-rpm t) - (setq rpm-spec-build-command "rpm")) + (if (not (executable-find "rpmbuild")) + (progn + (setq rpm-spec-build-command "rpm") + (setq rpm-spec-nobuild-option "--test"))) (make-local-variable 'paragraph-start) (setq paragraph-start (concat "$\\|" page-delimiter)) @@ -680,50 +711,56 @@ with no args, if that value is non-nil." (defun rpm-command-filter (process string) "Filter to process normal output." - (save-excursion - (set-buffer (process-buffer process)) + (with-current-buffer (process-buffer process) (save-excursion (goto-char (process-mark process)) (insert-before-markers string) (set-marker (process-mark process) (point))))) -; insert one space, or the number of tabs if rpm-spec-use-tabs is true -(defun rpm-insert-space-or-tabs (tabs) - (if rpm-spec-use-tabs - (if (> tabs 0) - (concat "\t" (rpm-insert-space-or-tabs (1- tabs))) - "") - " ")) - ;;------------------------------------------------------------ +(defvar rpm-change-log-uses-utc nil + "*If non-nil, \\[rpm-add-change-log-entry] will use Universal time (UTC). +If this is nil, it uses local time as returned by `current-time'. + +This variable is global by default, but you can make it buffer-local.") + +(defsubst rpm-change-log-date-string () + "Return the date string for today, inserted by \\[rpm-add-change-log-entry]. +If `rpm-change-log-uses-utc' is nil, \"today\" means the local time zone." + (format-time-string "%a %b %e %Y" nil rpm-change-log-uses-utc)) + +(defun rpm-goto-add-change-log-header () + "Find change log and add header (if needed) for today" + (rpm-goto-section "changelog") + (let* ((address (rpm-spec-user-mail-address)) + (fullname (or rpm-spec-user-full-name (user-full-name))) + (system-time-locale "C") + (string (concat "* " (rpm-change-log-date-string) " " + fullname " <" address ">" + (and rpm-spec-insert-changelog-version + (concat " - " (rpm-find-spec-version t)))))) + (if (not (search-forward string nil t)) + (insert "\n" string "\n") + (forward-line 2)))) + (defun rpm-add-change-log-entry (&optional change-log-entry) "Find change log and add an entry for today." - (interactive "P") - (goto-char (point-min)) - (if (search-forward-regexp "^%changelog[ \t]*$" nil t) - (let* ((address (or rpm-spec-user-mail-address user-mail-address)) - (fullname (or rpm-spec-user-full-name user-full-name)) - (string (concat "* " (substring (current-time-string) 0 11) - (substring (current-time-string) -4) " " - fullname " <" address "> " - (or - (and rpm-spec-insert-changelog-version - (or (and rpm-spec-insert-changelog-version-with-shell - (rpm-find-spec-version-with-shell)) - (rpm-find-spec-version)))) - ""))) - (if (not (search-forward string nil t)) - (insert "\n" string "\n") - (progn (next-line 1) - (beginning-of-line))) - (unless (eq (point) (1- (point-max))) - (insert "\n") - (previous-line 1)) - (insert "- ") - (if change-log-entry - (insert (concat (format "%s." change-log-entry))))) - (message "No \"%%changelog\" entry found..."))) + (interactive "sChange log entry: ") + (save-excursion + (rpm-goto-add-change-log-header) + (while (looking-at "^-") + (forward-line)) + (insert "- " change-log-entry "\n"))) + +(defun rpm-goto-add-change-log-entry () + "Goto change log and add an header for today (if needed)." + (interactive) + (rpm-goto-add-change-log-header) + (while (looking-at "^-") + (forward-line)) + (insert "- \n") + (end-of-line '0)) ;;------------------------------------------------------------ @@ -785,22 +822,23 @@ controls whether case is significant." (beginning-of-line) (if (not what) (setq what (rpm-completing-read "Tag: " rpm-tags-list))) - (if (string-match "^%" what) - (setq read-text (concat "Packagename for " what ": ") - insert-text (concat what " ")) - (setq read-text (concat what ": ") - insert-text (concat what ": "))) - (cond - ((string-equal what "Group") - (rpm-insert-group)) - ((string-equal what "Source") - (rpm-insert-n "Source")) - ((string-equal what "Patch") - (rpm-insert-n "Patch")) - (t - (if file-completion - (insert insert-text (read-file-name (concat read-text) "" "" nil) "\n") - (insert insert-text (read-from-minibuffer (concat read-text)) "\n"))))) + (let (read-text insert-text) + (if (string-match "^%" what) + (setq read-text (concat "Packagename for " what ": ") + insert-text (concat what " ")) + (setq read-text (concat what ": ") + insert-text (concat what ": "))) + (cond + ((string-equal what "Group") + (call-interactively 'rpm-insert-group)) + ((string-equal what "Source") + (rpm-insert-n "Source")) + ((string-equal what "Patch") + (rpm-insert-n "Patch")) + (t + (if file-completion + (insert insert-text (read-file-name (concat read-text) "" "" nil) "\n") + (insert insert-text (read-from-minibuffer (concat read-text)) "\n")))))) (defun rpm-topdir () (or @@ -816,7 +854,7 @@ controls whether case is significant." (save-excursion (goto-char (point-max)) (if (search-backward-regexp (concat "^" what "\\([0-9]*\\):") nil t) - (let ((release (1+ (string-to-int (match-string 1))))) + (let ((release (1+ (string-to-number (match-string 1))))) (forward-line 1) (let ((default-directory (concat (rpm-topdir) "/SOURCES/"))) (insert what (int-to-string release) ": " @@ -843,7 +881,7 @@ controls whether case is significant." (replace-match (concat what ": " (read-from-minibuffer (concat "New " what ": ") (match-string 1)))) - (message (concat what " tag not found..."))))))) + (message "%s tag not found..." what)))))) (defun rpm-change-n (what &optional arg) "Change given tag with possible number." @@ -857,25 +895,24 @@ controls whether case is significant." (concat what number ": " (read-file-name (concat "New " what number " file: ") "" "" nil (match-string 1))))) - (message (concat what " number \"" number "\" not found...")))))) + (message "%s number \"%s\" not found..." what number))))) (defun rpm-insert-group (group) "Insert Group tag." (interactive (list (rpm-completing-read "Group: " rpm-group-tags-list))) (beginning-of-line) - (insert "Group:" (rpm-insert-space-or-tabs 2) group "\n")) + (insert "Group: " group "\n")) (defun rpm-change-group (&optional arg) "Update Group tag." (interactive "p") (save-excursion (goto-char (point-min)) - (if (search-forward-regexp "^Group:[ \t]*\\(.*\\)$" nil t) + (if (search-forward-regexp "^Group: \\(.*\\)$" nil t) (replace-match - (concat "Group:" - (rpm-insert-space-or-tabs 2) - (rpm-completing-read "Group: " rpm-group-tags-list - nil nil (match-string 1)))) + (concat "Group: " + (insert (rpm-completing-read "Group: " rpm-group-tags-list + nil nil (match-string 1))))) (message "Group tag not found...")))) (defun rpm-insert-tag (&optional arg) @@ -894,10 +931,8 @@ controls whether case is significant." "Insert Packager tag." (interactive "p") (beginning-of-line) - (insert "Packager:" - (rpm-insert-space-or-tabs 1) - (or rpm-spec-user-full-name (user-full-name)) - " <" (or rpm-spec-user-mail-address (user-mail-address)) ">\n")) + (insert "Packager: " (or rpm-spec-user-full-name (user-full-name)) + " <" (rpm-spec-user-mail-address) ">\n")) (defun rpm-change-packager (&optional arg) "Update Packager tag." @@ -992,14 +1027,17 @@ leave point at previous location." (defun rpm-build (buildoptions) "Build this RPM package." - (setq rpm-buffer-name - (concat "*" rpm-spec-build-command " " - (file-name-nondirectory buffer-file-name) "*")) - (rpm-process-check rpm-buffer-name) - (if (get-buffer rpm-buffer-name) - (kill-buffer rpm-buffer-name)) - (create-file-buffer rpm-buffer-name) - (display-buffer rpm-buffer-name) + (if (and (buffer-modified-p) + (y-or-n-p (format "Buffer %s modified, save it? " (buffer-name)))) + (save-buffer)) + (let ((rpm-buffer-name + (concat "*" rpm-spec-build-command " " buildoptions " " + (file-name-nondirectory buffer-file-name) "*"))) + (rpm-process-check rpm-buffer-name) + (if (get-buffer rpm-buffer-name) + (kill-buffer rpm-buffer-name)) + (create-file-buffer rpm-buffer-name) + (display-buffer rpm-buffer-name)) (setq buildoptions (list buildoptions buffer-file-name)) (if (or rpm-spec-short-circuit rpm-spec-nobuild) (setq rpm-no-gpg t)) @@ -1009,8 +1047,6 @@ leave point at previous location." (setq buildoptions (cons "--clean" buildoptions))) (if rpm-spec-short-circuit (setq buildoptions (cons "--short-circuit" buildoptions))) - (if rpm-spec-no-deps - (setq buildoptions (cons "--nodeps" buildoptions))) (if (and (not (equal rpm-spec-timecheck "0")) (not (equal rpm-spec-timecheck ""))) (setq buildoptions (cons "--timecheck" (cons rpm-spec-timecheck @@ -1022,34 +1058,55 @@ leave point at previous location." (setq buildoptions (cons "--target" (cons rpm-spec-target buildoptions)))) (if rpm-spec-nobuild - (setq buildoptions (cons (if rpm-spec-old-rpm "--test" "--nobuild") - buildoptions))) + (setq buildoptions (cons rpm-spec-nobuild-option buildoptions))) + (if rpm-spec-quiet + (setq buildoptions (cons "--quiet" buildoptions))) (if rpm-spec-nodeps (setq buildoptions (cons "--nodeps" buildoptions))) (if (and rpm-spec-sign-gpg (not rpm-no-gpg)) (setq buildoptions (cons "--sign" buildoptions))) - (save-excursion - (set-buffer (get-buffer rpm-buffer-name)) - (goto-char (point-max))) - (let ((process - (apply 'start-process rpm-spec-build-command rpm-buffer-name - rpm-spec-build-command buildoptions))) - (if (and rpm-spec-sign-gpg (not rpm-no-gpg)) - (let ((rpm-passwd-cache (read-passwd "GPG passphrase: "))) - (process-send-string process (concat rpm-passwd-cache "\n")))) - (set-process-filter process 'rpm-command-filter))) + + (if rpm-spec-auto-topdir + (if (string-match ".*/SPECS/$" default-directory) + (let ((topdir (expand-file-name default-directory))) + (setq buildoptions + (cons + (concat "--define \"_topdir " + (replace-regexp-in-string "/SPECS/$" "" topdir) + "\"") + buildoptions))))) + + (progn + (defun list->string (lst) + (if (cdr lst) + (concat (car lst) " " (list->string (cdr lst))) + (car lst))) + (compilation-start (list->string (cons rpm-spec-build-command buildoptions)) 'rpmbuild-mode)) + + (if (and rpm-spec-sign-gpg (not rpm-no-gpg)) + (let ((build-proc (get-buffer-process + (get-buffer + (compilation-buffer-name "rpmbuild" nil nil)))) + (rpm-passwd-cache (read-passwd "GPG passphrase: "))) + (process-send-string build-proc (concat rpm-passwd-cache "\n"))))) (defun rpm-build-prepare (&optional arg) "Run a `rpmbuild -bp'." (interactive "p") - (setq rpm-no-gpg t) - (rpm-build "-bp")) + (if rpm-spec-short-circuit + (message "Cannot run `%s -bp' with --short-circuit" + rpm-spec-build-command) + (setq rpm-no-gpg t) + (rpm-build "-bp"))) (defun rpm-list-check (&optional arg) "Run a `rpmbuild -bl'." (interactive "p") - (setq rpm-no-gpg t) - (rpm-build "-bl")) + (if rpm-spec-short-circuit + (message "Cannot run `%s -bl' with --short-circuit" + rpm-spec-build-command) + (setq rpm-no-gpg t) + (rpm-build "-bl"))) (defun rpm-build-compile (&optional arg) "Run a `rpmbuild -bc'." @@ -1066,20 +1123,29 @@ leave point at previous location." (defun rpm-build-binary (&optional arg) "Run a `rpmbuild -bb'." (interactive "p") - (setq rpm-no-gpg nil) - (rpm-build "-bb")) + (if rpm-spec-short-circuit + (message "Cannot run `%s -bb' with --short-circuit" + rpm-spec-build-command) + (setq rpm-no-gpg nil) + (rpm-build "-bb"))) (defun rpm-build-source (&optional arg) "Run a `rpmbuild -bs'." (interactive "p") - (setq rpm-no-gpg nil) - (rpm-build "-bs")) + (if rpm-spec-short-circuit + (message "Cannot run `%s -bs' with --short-circuit" + rpm-spec-build-command) + (setq rpm-no-gpg nil) + (rpm-build "-bs"))) (defun rpm-build-all (&optional arg) "Run a `rpmbuild -ba'." (interactive "p") - (setq rpm-no-gpg nil) - (rpm-build "-ba")) + (if rpm-spec-short-circuit + (message "Cannot run `%s -ba' with --short-circuit" + rpm-spec-build-command) + (setq rpm-no-gpg nil) + (rpm-build "-ba"))) (defun rpm-process-check (buffer) "Check if BUFFER has a running process. @@ -1102,14 +1168,6 @@ command." (message (concat "Turned `--short-circuit' " (if rpm-spec-short-circuit "on" "off") "."))) -(defun rpm-toggle-no-deps (&optional arg) - "Toggle rpm-spec-no-deps." - (interactive "p") - (setq rpm-spec-no-deps (not rpm-spec-no-deps)) - (rpm-update-mode-name) - (message (concat "Turned `--nodeps' " - (if rpm-spec-no-deps "on" "off") "."))) - (defun rpm-toggle-rmsource (&optional arg) "Toggle `rpm-spec-rmsource'." (interactive "p") @@ -1131,9 +1189,17 @@ command." (interactive "p") (setq rpm-spec-nobuild (not rpm-spec-nobuild)) (rpm-update-mode-name) - (message (concat "Turned `" (if rpm-spec-old-rpm "--test" "--nobuild") "' " + (message (concat "Turned `" rpm-spec-nobuild-option "' " (if rpm-spec-nobuild "on" "off") "."))) +(defun rpm-toggle-quiet (&optional arg) + "Toggle `rpm-spec-quiet'." + (interactive "p") + (setq rpm-spec-quiet (not rpm-spec-quiet)) + (rpm-update-mode-name) + (message (concat "Turned `--quiet' " + (if rpm-spec-quiet "on" "off") "."))) + (defun rpm-toggle-sign-gpg (&optional arg) "Toggle `rpm-spec-sign-gpg'." (interactive "p") @@ -1161,17 +1227,17 @@ command." (defun rpm-update-mode-name () "Update `mode-name' according to values set." (setq mode-name "RPM-SPEC") - (setq modes (concat (if rpm-spec-add-attr "A") - (if rpm-spec-clean "C") - (if rpm-spec-nodeps "D") - (if rpm-spec-sign-gpg "G") - (if rpm-spec-nobuild "N") - (if rpm-spec-rmsource "R") - (if rpm-spec-short-circuit "S") - (if rpm-spec-no-deps "D") - )) - (if (not (equal modes "")) - (setq mode-name (concat mode-name ":" modes)))) + (let ((modes (concat (if rpm-spec-add-attr "A") + (if rpm-spec-clean "C") + (if rpm-spec-nodeps "D") + (if rpm-spec-sign-gpg "G") + (if rpm-spec-nobuild "N") + (if rpm-spec-rmsource "R") + (if rpm-spec-short-circuit "S") + (if rpm-spec-quiet "Q") + ))) + (if (not (equal modes "")) + (setq mode-name (concat mode-name ":" modes))))) ;;------------------------------------------------------------ @@ -1216,14 +1282,18 @@ command." (interactive "p") (save-excursion (goto-char (point-min)) - (if (search-forward-regexp "^Release:\\([ \t]*\\)\\(\\([^.\n]+\\.\\)*\\)\\([0-9]+\\)\\(.*\\)" nil t) - (let ((release (1+ (string-to-int (match-string 4))))) - (setq release (concat (match-string 1) (match-string 2) (int-to-string release) (match-string 5))) - (replace-match (concat "Release:" release)) - (message (concat "Release tag changed to " release "."))) - (if (search-forward-regexp "^Release:[ \t]*%{?\\([^}]*\\)}?$" nil t) - (rpm-increase-release-with-macros) - (message "No Release tag found..."))))) + (if (search-forward-regexp + ;; Try to find the last digit-only group of a dot-separated release string + (concat "^\\(Release[ \t]*:[ \t]*\\)" + "\\(.*[ \t\\.}]\\)\\([0-9]+\\)\\([ \t\\.%].*\\|$\\)") nil t) + (let ((release (1+ (string-to-number (match-string 3))))) + (setq release + (concat (match-string 2) (int-to-string release) (match-string 4))) + (replace-match (concat (match-string 1) release)) + (message "Release tag changed to %s." release)) + (if (search-forward-regexp "^Release[ \t]*:[ \t]*%{?\\([^}]*\\)}?$" nil t) + (rpm-increase-release-with-macros) + (message "No Release tag to increase found..."))))) ;;------------------------------------------------------------ @@ -1231,22 +1301,32 @@ command." "Get the value of FIELD, searching up to buffer position MAX. See `search-forward-regexp'." (save-excursion - (ignore-errors + (condition-case nil (let ((str (progn (goto-char (point-min)) - (search-forward-regexp (concat - field ":[ \t]*\\(.*?\\)[ \t]*$") max) + (search-forward-regexp + (concat "^" field ":[ \t]*\\(.*?\\)[ \t]*$") max) (match-string 1)))) - (if (string-match "%{?\\([^}]*\\)}?$" str) - (progn - (goto-char (point-min)) - (search-forward-regexp - (concat "%define[ \t]+" (substring str (match-beginning 1) - (match-end 1)) - "[ \t]+\\(.*\\)")) - (match-string 1)) - str))))) + ;; Try to expand macros + (if (string-match "\\(%{?\\(\\?\\)?\\)\\([a-zA-Z0-9_]*\\)\\(}?\\)" str) + (let ((start-string (substring str 0 (match-beginning 1))) + (end-string (substring str (match-end 4)))) + (if (progn + (goto-char (point-min)) + (search-forward-regexp + (concat "%\\(define\\|global\\)[ \t]+" + (match-string 3 str) + "[ \t]+\\(.*\\)") nil t)) + ;; Got it - replace. + (concat start-string (match-string 2) end-string) + (if (match-string 2 str) + ;; Conditionally evaluated macro - remove it. + (concat start-string end-string) + ;; Leave as is. + str))) + str)) + (error nil)))) (defun rpm-find-spec-version (&optional with-epoch) "Get the version string. @@ -1264,85 +1344,107 @@ if one is present in the file." version (and release (concat "-" release))))))) -(defun rpm--with-temp-file (prefix f) - (let ((file (make-temp-file prefix))) - (unwind-protect - (funcall f file) - (delete-file file)))) - -(defun rpm-find-spec-version-with-shell () - "Find the version and release with the rpm command - more robust but slower than the lisp version" - (rpm--with-temp-file "spec" (lambda (tmpfile) - (write-region (point-min) (point-max) tmpfile nil 1) - (let ((relver)) - (with-temp-buffer - (apply 'call-process "rpm" nil t nil - (list "-q" "--qf" "'%{VERSION}-%{RELEASE}\\n'" "--specfile" tmpfile)) - (goto-char (point-min)) - (if (re-search-forward "\\([0-9]+.+\\)" nil t) - (setq relver (match-string 1))) - ) - relver) - ))) - (defun rpm-increase-release-with-macros () (save-excursion (let ((str (progn (goto-char (point-min)) - (search-forward-regexp (concat "Release:[ \t]*\\(.+\\).*$") nil) - (match-string 1))) - (increase-macro (lambda (macros) - (goto-char (point-min)) - (if (search-forward-regexp - (concat "%define[ \t]+" macros - "\\([ \t]+\\)\\(\\([^.\n]+\\.\\)*\\)\\([0-9]+\\)\\(.*\\)") nil t) - (let ((dinrel (concat macros (match-string 1) (match-string 2) - (int-to-string (1+ (string-to-int - (match-string 4)))) - (match-string 5)))) - (replace-match (concat "%define " dinrel)) - (message (concat "Release tag changed to " dinrel ".")) - t))))) - - (if (string-match "%{?\\([^}]*\\)}?$" str) - (let ((macros (substring str (match-beginning 1) (match-end 1)))) - (or (funcall increase-macro macros) - (and (search-forward-regexp - (concat "%define[ \t]+" macros "[ \t]+%mkrel[ \t]+%{rel}") nil t) - (funcall increase-macro "rel")) - (and (search-forward-regexp "\\(%mkrel[ \t]+\\)\\([0-9]+\\)$" nil t) - (replace-match (concat (match-string 1) (int-to-string (1+ (string-to-int (match-string 2))))))) - )))))) + (search-forward-regexp "^Release[ \t]*:[ \t]*\\(.+\\).*$" nil) + (match-string 1)))) + (let ((inrel + (if (string-match "%{?\\([^}]*\\)}?$" str) + (progn + (goto-char (point-min)) + (let ((macros (substring str (match-beginning 1) + (match-end 1)))) + (search-forward-regexp + (concat "%define[ \t]+" macros + "[ \t]+\\(\\([0-9]\\|\\.\\)+\\)\\(.*\\)")) + (concat macros " " (int-to-string (1+ (string-to-number + (match-string 1)))) + (match-string 3)))) + str))) + (let ((dinrel inrel)) + (replace-match (concat "%define " dinrel)) + (message "Release tag changed to %s." dinrel)))))) ;;------------------------------------------------------------ (defun rpm-spec-initialize () "Create a default spec file if one does not exist or is empty." - (let (file name version (release "1")) + (let (file name version (release rpm-spec-default-release)) (setq file (if (buffer-file-name) (file-name-nondirectory (buffer-file-name)) (buffer-name))) - (string-match "\\(.*\\).spec" file) - (setq name (match-string 1 file)) + (cond + ((eq (string-match "\\(.*\\)-\\([^-]*\\)-\\([^-]*\\).spec" file) 0) + (setq name (match-string 1 file)) + (setq version (match-string 2 file)) + (setq release (match-string 3 file))) + ((eq (string-match "\\(.*\\)-\\([^-]*\\).spec" file) 0) + (setq name (match-string 1 file)) + (setq version (match-string 2 file))) + ((eq (string-match "\\(.*\\).spec" file) 0) + (setq name (match-string 1 file)))) + + (if rpm-spec-indent-heading-values + (insert + "Summary: " + "\nName: " (or name "") + "\nVersion: " (or version "") + "\nRelease: " (or release "") + (if rpm-spec-default-epoch + (concat "\nEpoch: " + (int-to-string rpm-spec-default-epoch)) + "") + "\nLicense: " + "\nGroup: " + "\nURL: " + "\nSource0: %{name}-%{version}.tar.gz" + "\nBuildRoot: " rpm-spec-default-buildroot) + (insert + "Summary: " + "\nName: " (or name "") + "\nVersion: " (or version "") + "\nRelease: " (or release "") + (if rpm-spec-default-epoch + (concat "\nEpoch: " (int-to-string rpm-spec-default-epoch)) + "") + "\nLicense: " + "\nGroup: " + "\nURL: " + "\nSource0: %{name}-%{version}.tar.gz" + "\nBuildRoot: " rpm-spec-default-buildroot)) (insert - "%define name " (or name "") - "\n%define version " (or version "") - "\n%define release %mkrel " (or release "") - "\n\nSummary:" (rpm-insert-space-or-tabs 1) - "\nName:" (rpm-insert-space-or-tabs 2) "%{name}" - "\nVersion:" (rpm-insert-space-or-tabs 1) "%{version}" - "\nRelease:" (rpm-insert-space-or-tabs 1) "%{release}" - "\nSource0:" (rpm-insert-space-or-tabs 1) "%{name}-%{version}.tar.bz2" - "\nLicense:" (rpm-insert-space-or-tabs 1) - "\nGroup:" (rpm-insert-space-or-tabs 2) - "\nUrl:" (rpm-insert-space-or-tabs 2) - "\n\n%description\n" - "\n%prep\n%setup -q\n\n%build\n\n%install" - "\n\n%files\n")) - (goto-char (point-min))) + "\n\n%description\n" + "\n%prep" + "\n%setup -q" + "\n\n%build\n" + (or rpm-spec-default-build-section "") + "\n%install\n" + (or rpm-spec-default-install-section "") + "\n%clean\n" + (or rpm-spec-default-clean-section "") + "\n\n%files" + "\n%defattr(-,root,root,-)" + "\n%doc\n" + "\n\n%changelog\n") + + (end-of-line 1) + (rpm-add-change-log-entry "Initial build."))) + +;;------------------------------------------------------------ + +(defun rpm-spec-user-mail-address () + "User mail address helper." + (cond + (rpm-spec-user-mail-address + rpm-spec-user-mail-address) + ((fboundp 'user-mail-address) + (user-mail-address)) + (t + user-mail-address))) ;;------------------------------------------------------------ @@ -1352,11 +1454,13 @@ if one is present in the file." (message (concat "rpm-spec-mode version " rpm-spec-mode-version - " by Stig Bjørlykke, "))) + " by Stig Bjørlykke, "))) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.spec$" . rpm-spec-mode)) +;;;###autoload(add-to-list 'auto-mode-alist '("\\.spec\\(\\.in\\)?$" . rpm-spec-mode)) (provide 'rpm-spec-mode) +;;;###autoload +(define-compilation-mode rpmbuild-mode "RPM build" "" + (set (make-local-variable 'compilation-disable-input) t)) ;;; rpm-spec-mode.el ends here -- cgit v1.2.1