branch: elpa/rpm-spec-mode
commit d628b77f9d39aa44340eb5975abbc59286509ba6
Author: stig <s...@bjorlykke.org>
Commit: stig <s...@bjorlykke.org>

    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 <t...@redhat.com> and Trond Eivind Glomsr�d
 ;;          <t...@redhat.com> for Red Hat adaptions and some fixes.
 ;;     Chmouel Boudjnah <chmo...@mandrakesoft.com> for Mandrake fixes.
+;;     Ville Skytt�  <s...@xemacs.org> 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, <st...@tihlde.org>")))
 
-;;;###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

Reply via email to