emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: commit style redux


From: Thien-Thi Nguyen
Subject: Re: commit style redux
Date: Sat, 16 Jan 2010 10:10:26 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.91 (gnu/linux)

() Glenn Morris <address@hidden>
() Fri, 15 Jan 2010 22:00:09 -0500

   I use M-x log-edit-insert-changelog to auto-populate the vc-log
   buffer from my ChangeLog entries. Is this doing the right
   thing, or does Emacs need to be changed?

   It creates log entries like this:

     * cedet/ede/cpp-root.el (ede-cpp-root-project): Foo

     * srecode/doc-cpp.srt, srecode/doc-default.srt: Bar

     * ede.texi (ede-target):
     * org.texi (Refiling notes): Qux

   The paths are relative to where each ChangeLog file is, rather
   than relative to the root of the project. If there are two
   files with the same basename in different subdirectories,
   things might get ambiguous.

FWIW, the following substandard (undocumented except for this
message, works for me on 23.0.60.9, tuned to my tastes) code
disambiguates the ChangeLog greps.  It basically:

- looks at each named ChangeLog in the "git status" output;
- inserts the first entry, stripping/unifying the "subject line"
  (sanity-checking that they are all string=, in the process);
- modifies the entries' "* foo" to contain the ChangeLog's
  directory parent prefix (if any) from the project root, so that
  "abc/def/ChangeLog" entry "* foo (bar): baz" ends up looking
  like "* abc/def/foo (bar): baz".

The OLDGIT cruft is for Git 1.5.3.5, which i have transitioned
away from in the last few months and can probably be safely
ignored.

With this, i do "git commit" (either directly via M-x compile) or
through some VC keybinding, `C-c C-d' to populate the buffer, and
`C-c C-c' to finish.

Doubtless a SMOP can get this adapted to (current) Emacs (current)
VC (current) Git with support for other DVCSes as well.

thi

________________________________________________________________________
;;; this is arguably the wrong way to go about things...

(defun commit-log-from-git-status (relative-file-names)
  (let ((changelogs (or (remove-if-not (lambda (s)
                                         (string-match "ChangeLog$" s))
                                       relative-file-names)
                        (error "No ChangeLog files")))
        head body)
    (dolist (fn changelogs)
      (with-temp-buffer
        (insert-file-contents fn)
        (search-forward "\n\n" nil nil 2)
        (push (buffer-substring (point-min) (point)) head)
        (unless (or (null (cdr head))
                    (string= (car head) (cadr head)))
          (error "head mismatch for %s" fn))
        (push (buffer-substring
               (point) (progn (re-search-forward change-log-start-entry-re)
                              (match-beginning 0)))
              body)))
    (setq head (car head)
          head (and (string-match "\n\n\t" head)
                    (substring head (match-end 0)))
          body (map 'list
                    (lambda (fn bod)
                      (let ((pre (and (string-match "ChangeLog$" fn)
                                      (substring fn 0 (match-beginning 0)))))
                        (with-temp-buffer
                          (insert bod)
                          (goto-char (point-min))
                          (while (search-forward "\t* " nil 1)
                            (insert pre))
                          (while (re-search-backward "^\t" nil t)
                            (delete-char 1))
                          (buffer-string))))
                    (nreverse changelogs) body))
    (apply 'concat head body)))

(defun scan-git-status-and-insert-commit-log ()
  (interactive)
  (let ((oldgitp (equal "1" (getenv "OLDGIT")))
        (default-directory (expand-file-name ".."))
        (max (save-excursion
               (if (search-forward "Changed but not updated" nil t)
                   (match-beginning 0)
                 (point-max))))
        sub acc)
    (unless oldgitp
      (let ((root default-directory))
        (find-if (lambda (buf)
                   (with-current-buffer buf
                     (when (and (eq 'compilation-mode major-mode)
                                (eq 'run (process-status buf))
                                (setq sub (expand-file-name default-directory))
                                (search root sub))
                       (setq sub (substring sub (1+ (mismatch root sub)))))))
                 (buffer-list))))
    (save-excursion
      (while (re-search-forward "\tmodified: +\\(.+$\\)" max t)
        (push (concat sub (match-string 1)) acc)))
    (insert (commit-log-from-git-status (nreverse acc)))))

(defvar commit-editmsg-map
  (let ((m (copy-keymap text-mode-map)))
    (define-keys m
      "\C-c\C-d" 'scan-git-status-and-insert-commit-log
      "\C-c\C-c" 'server-edit)
    m))

(defun commit-editmsg-setup ()
  (when (string-match ".git/COMMIT_EDITMSG" (or buffer-file-name ""))
    (set-buffer-file-coding-system 'utf-8)
    (use-local-map commit-editmsg-map)))

(add-hook 'server-visit-hook 'commit-editmsg-setup)

;;; vc-git-hacking.el ends here




reply via email to

[Prev in Thread] Current Thread [Next in Thread]