Greetings earthlings, It's 2008 and time to get away from CVS. But, where to? For me, Git is a good choice. We'll see in another 15 years.
See also <http://www.gnuvola.org/wip/> for other bits of play (some suitable for Emacs directly, others only (very) indirectly). thi ___________________________________________________________________ ;;; cvs-to-git.el --- Rescue a project from its CVS repo ;; Copyright (C) 2008 Thien-Thi Nguyen ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Don't let your projects rot in CVS! ;; Use `cvs-to-git' to rescue them! ;;; Code: (defvar cvs-to-git-CVSROOT "~/cvs" "Repository location for \"git cvsimport -d\".") (defvar cvs-to-git-usermap "~/.cvsps/.ttn" "Filename for \"git cvsimport -A\". This file maps usernames to real names / email addresses. Each line has the form: username=Real Name <email-address>") (defvar cvs-to-git-finish-fixup-hook nil "Normal hook for `cvs-to-git-finish-fixup'. See, for example, `cvs-to-git-ttn-fixups'.") (defvar cvs-to-git-in-progress nil "List of buffers hosting a cvs-to-git session. Internal variable; do not use.") (defun cvs-to-git (project under) "Initiate a rescue for PROJECT with output dir UNDER/PROJECT. When the \"git cvsimport\" is done, call `cvs-to-git-start-fixup'." (interactive "sProject: \nDUnder: ") (let ((newdir (expand-file-name project under))) (when (file-exists-p newdir) (error "%s exists" newdir))) (push (compile (format "cd %s ; git cvsimport -A %s -d %s -C %s -k -u -v %s" under cvs-to-git-usermap cvs-to-git-CVSROOT project project)) cvs-to-git-in-progress) (add-hook 'compilation-finish-functions 'cvs-to-git-start-fixup nil t) (set (make-local-variable 'cvs-to-git-project) project) (rename-buffer (format "CVS to GIT: %s" project)) (message "Conversion into %s started (check back later)" (expand-file-name project))) (defun cvs-to-git-start-fixup (buffer happenings) "Prepare BUFFER for further fixups. Change to outline mode; convert the first line into a heading; at eob, insert HAPPENINGS as a header, insert header \"tags\" with following lines having the form: - CVSTAG SHA1 DATE UTCTIME Lastly, arrange for `C-c C-c' to run `cvs-to-git-finish-fixup'." (when (memq buffer cvs-to-git-in-progress) (let ((project (symbol-value 'cvs-to-git-project)) tags) (setq cvs-to-git-in-progress (delq buffer cvs-to-git-in-progress)) (setq default-directory (file-name-as-directory (expand-file-name project))) (outline-mode) (goto-char (point-min)) (delete-region (point) (line-end-position)) (insert "* \"git cvsimport\" output") (goto-char (point-max)) (insert "\n\n\n* \"git cvsimport\" status: " happenings) (insert "\n\n* description (one line, goes into .git/description)\n") (save-excursion (insert "[write me]\n") (insert "\n\n* tags (edit first column then type C-c C-c to finish)\n") (setq tags (split-string (shell-command-to-string "git tag"))) (dolist (tag tags) (insert "- " tag " " (shell-command-to-string (format "git show %s %s | sed '%s'" "--pretty=format:\"foo: %H %ci%n\"" tag "/^foo: /!d;s///;s/ +0000$//"))))) (let ((m (copy-keymap outline-mode-map))) (define-key m "\C-c\C-c" 'cvs-to-git-finish-fixup) (use-local-map m)) (setq buffer-read-only nil) (message "%s ready for fixup" buffer)))) (defun cvs-to-git-finish-fixup () "Finish fixing up the Git repo (see `cvs-to-git-start-fixup'). Interpret content of section \"tags\" as lines with format: GITTAG CVSTAG SHA1 DATE UTCTIME In all cases, delete CVSTAG. If GITTAG is \"-\", do nothing else. Otherwise, tag SHA1 w/ GITTAG using the two line annotation: DATE UTCTIME >From CVS tag CVSTAG. Insert tagging operation output after each line. When done, insert output of \"git tag -n 2\" and run-hook `cvs-to-git-finish-fixup-hook'." (interactive) (goto-char (point-max)) (search-backward "* description") (write-region (line-beginning-position 2) (line-beginning-position 3) ".git/description") (search-forward "* tags") (forward-line 1) (while (< (point) (point-max)) (let ((ls (split-string (buffer-substring (point) (line-end-position))))) (forward-line 1) (unless (string= "-" (car ls)) (with-temp-file "TMP" (insert (nth 3 ls) " " (nth 4 ls) "\n" "From CVS tag " (nth 1 ls) ".\n")) (call-process "git" nil t t "tag" "-a" "-F" "TMP" (nth 0 ls) (nth 2 ls))) (call-process "git" nil t t "tag" "-d" (nth 1 ls)))) (when (file-exists-p "TMP") (delete-file "TMP")) (insert "\n") (call-process "git" nil t t "tag" "-n" "2") (run-hooks 'cvs-to-git-finish-fixup-hook) (message "%s fixup done" (current-buffer))) (defun cvs-to-git-ttn-fixups () "Do miscellaneous ttn-preferred fixups. Specifically: chmod +w .git/hooks/post-commit git config core.filemode false git ls-files -z | xargs -0 chmod -w (create files \".git/info/attributes\" and \".last-release\") This is meant to be added to `cvs-to-git-finish-fixup-hook'." (set-file-modes ".git/hooks/post-commit" #o755) (call-process "git" nil nil nil "config" "core.filemode" "false") (shell-command "git ls-files -z | xargs -0 chmod -w") (with-temp-file ".git/info/attributes" (insert "*.el\tdiff=lisp\n" "*.scm\tdiff=lisp\n")) (with-temp-file ".last-release" (shell-command "git tag -n | sort -brk 2,3 | sed 's/ .*//;1q'" t))) (provide 'cvs-to-git) ;;; cvs-to-git.el ends here _______________________________________________ gnu-emacs-sources mailing list [email protected] http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources
