branch: elpa/rpm-spec-mode
commit d628b77f9d39aa44340eb5975abbc59286509ba6
Author: stig <[email protected]>
Commit: stig <[email protected]>
Added 5 patches from Fedora emacs-rpm-spec-mode.
The patches was marked xemacs, compilation, utc, changelog and
goto-add-changelog-entry, and has been contributed over time.
---
rpm-spec-mode.el | 496 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 355 insertions(+), 141 deletions(-)
diff --git a/rpm-spec-mode.el b/rpm-spec-mode.el
index bc147b4907..7f8c242bf3 100644
--- a/rpm-spec-mode.el
+++ b/rpm-spec-mode.el
@@ -20,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.
@@ -33,12 +33,13 @@
;; Tim Powers <[email protected]> and Trond Eivind Glomsr�d
;; <[email protected]> for Red Hat adaptions and some fixes.
;; Chmouel Boudjnah <[email protected]> for Mandrake fixes.
+;; Ville Skytt� <[email protected]> for some 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.
@@ -61,6 +62,7 @@
;;
;;; Code:
+(require 'compile)
(defconst rpm-spec-mode-version "0.12" "Version of `rpm-spec-mode'.")
@@ -70,7 +72,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)
@@ -95,7 +97,7 @@ timecheck age."
:group 'rpm-spec)
(defcustom rpm-spec-buildroot ""
- "Override the BuildRoot tag with directory <dir>."
+ "When building, override the BuildRoot tag with directory <dir>."
:type 'string
:group 'rpm-spec)
@@ -125,11 +127,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
@@ -142,11 +153,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)
@@ -179,8 +185,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)
@@ -188,88 +236,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")
"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.6.0 sources, file build/parseSpec.c: partList[].
+ '("build" "changelog" "check" "clean" "description" "files"
+ "install" "package" "post" "postun" "pretrans" "posttrans"
+ "pre" "prep" "preun" "trigger" "triggerin" "triggerpostun"
+ "triggerprein" "triggerun" "verifyscript") 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 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 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\".")
@@ -281,24 +346,31 @@ 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[].")
+ ;; From RPM 4.4.9 sources, file build/parsePreamble.c: preambleList[], and
+ ;; a few macros that aren't tags, but useful here.
'(("AutoProv")
("AutoReq")
("AutoReqProv")
("BuildArch")
("BuildArchitectures")
("BuildConflicts")
+ ("BuildEnhances")
+ ("BuildPlatforms")
("BuildPreReq")
("BuildRequires")
("BuildRoot")
+ ("BuildSuggests")
("Conflicts")
- ("Copyright")
+ ("CVSId")
("%description")
("Distribution")
+ ("DistTag")
("DistURL")
("DocDir")
+ ("Enhances")
("Epoch")
("ExcludeArch")
("ExcludeOS")
@@ -308,6 +380,8 @@ value returned by function `user-mail-address'."
("Group")
("Icon")
("%ifarch")
+ ("Keyword")
+ ("Keywords")
("License")
("Name")
("NoPatch")
@@ -322,17 +396,40 @@ value returned by function `user-mail-address'."
("Provides")
("Release")
("Requires")
- ("RHNPlatform")
- ("Serial")
+ ("RepoTag")
("Source")
+ ("Suggests")
("Summary")
+ ("SVNId")
("URL")
+ ("Variant")
+ ("Variants")
("Vendor")
- ("Version"))
+ ("Version")
+ ("XMajor")
+ ("XMinor")
+ )
"List of elements that are valid 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
- ;; From RPM 4.1 sources, file GROUPS.
+ ;; From RPM 4.4.9 sources, file GROUPS.
'(("Amusements/Games")
("Amusements/Graphics")
("Applications/Archiving")
@@ -393,6 +490,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)
@@ -421,9 +519,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-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)
@@ -466,6 +565,8 @@ value returned by function `user-mail-address'."
: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
@@ -488,33 +589,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\\)?[ \t]+\\(.*\\)\n" 2 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
@@ -526,6 +635,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.
@@ -553,13 +664,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))
@@ -597,22 +708,48 @@ with no args, if that value is non-nil."
;;------------------------------------------------------------
-(defun rpm-add-change-log-entry (&optional change-log-entry)
- "Find change log and add an entry for today."
- (interactive "sChange log entry: ")
- (save-excursion
+(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 (or rpm-spec-user-mail-address (user-mail-address)))
+ (let* ((address (rpm-spec-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) " "
+ (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))))))
+ (concat " - " (rpm-find-spec-version t))))))
(if (not (search-forward string nil t))
(insert "\n" string "\n")
- (forward-line 2))
- (insert "- " change-log-entry "\n"))))
+ (forward-line 2))))
+
+(defun rpm-add-change-log-entry (&optional change-log-entry)
+ "Find change log and add an entry for today."
+ (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))
;;------------------------------------------------------------
@@ -732,7 +869,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."
@@ -746,7 +883,7 @@ 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."
@@ -783,7 +920,7 @@ controls whether case is significant."
(interactive "p")
(beginning-of-line)
(insert "Packager: " (or rpm-spec-user-full-name (user-full-name))
- " <" (or rpm-spec-user-mail-address (user-mail-address)) ">\n"))
+ " <" (rpm-spec-user-mail-address) ">\n"))
(defun rpm-change-packager (&optional arg)
"Update Packager tag."
@@ -878,6 +1015,9 @@ leave point at previous location."
(defun rpm-build (buildoptions)
"Build this RPM package."
+ (if (and (buffer-modified-p)
+ (y-or-n-p (format "Buffer %s modified, save it? " (buffer-name))))
+ (save-buffer))
(setq rpm-buffer-name
(concat "*" rpm-spec-build-command " " buildoptions " "
(file-name-nondirectory buffer-file-name) "*"))
@@ -906,29 +1046,44 @@ 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")
(if rpm-spec-short-circuit
- (message (concat "Cannot run `" rpm-spec-build-command
- " -bp' with --short-circuit"))
+ (message "Cannot run `%s -bp' with --short-circuit"
+ rpm-spec-build-command)
(setq rpm-no-gpg t)
(rpm-build "-bp")))
@@ -936,8 +1091,8 @@ leave point at previous location."
"Run a `rpmbuild -bl'."
(interactive "p")
(if rpm-spec-short-circuit
- (message (concat "Cannot run `" rpm-spec-build-command
- " -bl' with --short-circuit"))
+ (message "Cannot run `%s -bl' with --short-circuit"
+ rpm-spec-build-command)
(setq rpm-no-gpg t)
(rpm-build "-bl")))
@@ -957,8 +1112,8 @@ leave point at previous location."
"Run a `rpmbuild -bb'."
(interactive "p")
(if rpm-spec-short-circuit
- (message (concat "Cannot run `" rpm-spec-build-command
- " -bb' with --short-circuit"))
+ (message "Cannot run `%s -bb' with --short-circuit"
+ rpm-spec-build-command)
(setq rpm-no-gpg nil)
(rpm-build "-bb")))
@@ -966,8 +1121,8 @@ leave point at previous location."
"Run a `rpmbuild -bs'."
(interactive "p")
(if rpm-spec-short-circuit
- (message (concat "Cannot run `" rpm-spec-build-command
- " -bs' with --short-circuit"))
+ (message "Cannot run `%s -bs' with --short-circuit"
+ rpm-spec-build-command)
(setq rpm-no-gpg nil)
(rpm-build "-bs")))
@@ -975,8 +1130,8 @@ leave point at previous location."
"Run a `rpmbuild -ba'."
(interactive "p")
(if rpm-spec-short-circuit
- (message (concat "Cannot run `" rpm-spec-build-command
- " -ba' with --short-circuit"))
+ (message "Cannot run `%s -ba' with --short-circuit"
+ rpm-spec-build-command)
(setq rpm-no-gpg nil)
(rpm-build "-ba")))
@@ -1022,9 +1177,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")
@@ -1059,6 +1222,7 @@ command."
(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))))
@@ -1106,14 +1270,18 @@ command."
(interactive "p")
(save-excursion
(goto-char (point-min))
- (if (search-forward-regexp "^Release:[ \t]*\\([0-9]+\\)\\(.*\\)" nil t)
- (let ((release (1+ (string-to-int (match-string 1)))))
- (setq release (concat (int-to-string release) (match-string 2)))
- (replace-match (concat "Release: " release))
- (message (concat "Release tag changed to " release ".")))
- (if (search-forward-regexp "^Release:[ \t]*%{?\\([^}]*\\)}?$" nil t)
+ (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-int (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 found...")))))
+ (message "No Release tag to increase found...")))))
;;------------------------------------------------------------
@@ -1121,22 +1289,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.
@@ -1159,7 +1337,7 @@ if one is present in the file."
(let ((str
(progn
(goto-char (point-min))
- (search-forward-regexp (concat "Release:[ \t]*\\(.+\\).*$") nil)
+ (search-forward-regexp "^Release[ \t]*:[ \t]*\\(.+\\).*$" nil)
(match-string 1))))
(let ((inrel
(if (string-match "%{?\\([^}]*\\)}?$" str)
@@ -1176,13 +1354,13 @@ if one is present in the file."
str)))
(setq dinrel inrel)
(replace-match (concat "%define " dinrel))
- (message (concat "Release tag changed to " 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)))
@@ -1197,30 +1375,64 @@ if one is present in the 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
- "Summary: "
- "\nName: " (or name "")
- "\nVersion: " (or version "")
- "\nRelease: " (or release "")
- "\nLicense: "
- "\nGroup: "
- "\nURL: "
- "\nSource0: %{name}-%{version}.tar.gz"
- "\nBuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot"
"\n\n%description\n"
"\n%prep"
"\n%setup -q"
- "\n\n%build"
- "\n\n%install"
- "\nrm -rf $RPM_BUILD_ROOT"
- "\n\n%clean"
- "\nrm -rf $RPM_BUILD_ROOT"
+ "\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")
- (rpm-add-change-log-entry "Initial build.\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)))
;;------------------------------------------------------------
@@ -1232,9 +1444,11 @@ if one is present in the file."
rpm-spec-mode-version
" by Stig Bj�rlykke, <[email protected]>")))
-;;;###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