{"thread":{"id":"11939","subject":"[PATCH 2/4] git.el: Added a command to amend a commit.","startedAt":"2008-02-07T12:50:39Z","lastAt":"2008-02-07T13:29:30Z","messageCount":3,"participants":["Alexandre Julliard","Sergei Organov","David Kastrup"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"67789","messageId":"87ve51orq8.fsf@wine.dyndns.org","threadId":"11939","inReplyTo":null,"subject":"[PATCH 2/4] git.el: Added a command to amend a commit.","fromName":"Alexandre Julliard","fromEmail":"julliard@winehq.org","sentAt":"2008-02-07T12:50:39Z","receivedAt":"2008-02-07T12:50:39Z","isPatch":true,"sender":{"key":"julliard@winehq.org","avatar":null},"body":"It reverts the commit and sets up the status and edit log buffer to\nallow making changes and recommitting it. Bound to C-c C-a.\n\nSigned-off-by: Alexandre Julliard <julliard@winehq.org>\n---\n contrib/emacs/git.el |   74 +++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 73 insertions(+), 1 deletions(-)\n\ndiff --git a/contrib/emacs/git.el b/contrib/emacs/git.el\nindex 58d72a5..5519ed1 100644\n--- a/contrib/emacs/git.el\n+++ b/contrib/emacs/git.el\n@@ -740,6 +740,27 @@ Return the list of files that haven't been handled.\"\n     (git-refresh-files)\n     (git-refresh-ewoc-hf git-status)))\n \n+(defun git-mark-files (status files)\n+  \"Mark all the specified FILES, and unmark the others.\"\n+  (setq files (sort files #'string-lessp))\n+  (let ((file (and files (pop files)))\n+        (node (ewoc-nth status 0)))\n+    (while node\n+      (let ((info (ewoc-data node)))\n+        (if (and file (string-equal (git-fileinfo->name info) file))\n+            (progn\n+              (unless (git-fileinfo->marked info)\n+                (setf (git-fileinfo->marked info) t)\n+                (setf (git-fileinfo->needs-refresh info) t))\n+              (setq file (pop files))\n+              (setq node (ewoc-next status node)))\n+          (when (git-fileinfo->marked info)\n+            (setf (git-fileinfo->marked info) nil)\n+            (setf (git-fileinfo->needs-refresh info) t))\n+          (if (and file (string-lessp file (git-fileinfo->name info)))\n+              (setq file (pop files))\n+            (setq node (ewoc-next status node))))))))\n+\n (defun git-marked-files ()\n   \"Return a list of all marked files, or if none a list containing just the file at cursor position.\"\n   (unless git-status (error \"Not in git-status buffer.\"))\n@@ -1218,7 +1239,8 @@ Return the list of files that haven't been handled.\"\n       (goto-char (point-min))\n       (when (re-search-forward \"\\n+\\\\'\" nil t)\n         (replace-match \"\\n\" t t))\n-      (when sign-off (git-append-sign-off committer-name committer-email)))))\n+      (when sign-off (git-append-sign-off committer-name committer-email)))\n+    buffer))\n \n (defun git-commit-file ()\n   \"Commit the marked file(s), asking for a commit message.\"\n@@ -1251,6 +1273,52 @@ Return the list of files that haven't been handled.\"\n       (setq buffer-file-coding-system coding-system)\n       (re-search-forward (regexp-quote (concat git-log-msg-separator \"\\n\")) nil t))))\n \n+(defun git-setup-commit-buffer (commit)\n+  \"Setup the commit buffer with the contents of COMMIT.\"\n+  (let (author-name author-email subject date msg)\n+    (with-temp-buffer\n+      (let ((coding-system (git-get-logoutput-coding-system)))\n+        (git-call-process-env t nil \"log\" \"-1\" commit)\n+        (goto-char (point-min))\n+        (when (re-search-forward \"^Author: *\\\\(.*\\\\) <\\\\(.*\\\\)>$\" nil t)\n+          (setq author-name (match-string 1))\n+          (setq author-email (match-string 2)))\n+        (when (re-search-forward \"^Date: *\\\\(.*\\\\)$\" nil t)\n+          (setq date (match-string 1)))\n+        (while (re-search-forward \"^    \\\\(.*\\\\)$\" nil t)\n+          (push (match-string 1) msg))\n+        (setq msg (nreverse msg))\n+        (setq subject (pop msg))\n+        (while (and msg (zerop (length (car msg))) (pop msg)))))\n+    (git-setup-log-buffer (get-buffer-create \"*git-commit*\")\n+                          author-name author-email subject date\n+                          (mapconcat #'identity msg \"\\n\"))))\n+\n+(defun git-get-commit-files (commit)\n+  \"Retrieve the list of files modified by COMMIT.\"\n+  (let (files)\n+    (with-temp-buffer\n+      (git-call-process-env t nil \"diff-tree\" \"-r\" \"-z\" \"--name-only\" \"--no-commit-id\" commit)\n+      (goto-char (point-min))\n+      (while (re-search-forward \"\\\\([^\\0]*\\\\)\\0\" nil t 1)\n+        (push (match-string 1) files)))\n+    files))\n+\n+(defun git-amend-commit ()\n+  \"Undo the last commit on HEAD, and set things up to commit an\n+amended version of it.\"\n+  (interactive)\n+  (unless git-status (error \"Not in git-status buffer.\"))\n+  (when (git-empty-db-p) (error \"No commit to amend.\"))\n+  (let* ((commit (git-rev-parse \"HEAD\"))\n+         (files (git-get-commit-files commit)))\n+    (git-call-process-env nil nil \"reset\" \"--soft\" \"HEAD^\")\n+    (git-update-status-files (copy-sequence files) 'uptodate)\n+    (git-mark-files git-status files)\n+    (git-refresh-files)\n+    (git-setup-commit-buffer commit)\n+    (git-commit-file)))\n+\n (defun git-find-file ()\n   \"Visit the current file in its own buffer.\"\n   (interactive)\n@@ -1329,6 +1397,7 @@ Return the list of files that haven't been handled.\"\n \n (unless git-status-mode-map\n   (let ((map (make-keymap))\n+        (commit-map (make-sparse-keymap))\n         (diff-map (make-sparse-keymap))\n         (toggle-map (make-sparse-keymap)))\n     (suppress-keymap map)\n@@ -1337,6 +1406,7 @@ Return the list of files that haven't been handled.\"\n     (define-key map \" \"   'git-next-file)\n     (define-key map \"a\"   'git-add-file)\n     (define-key map \"c\"   'git-commit-file)\n+    (define-key map \"\\C-c\" commit-map)\n     (define-key map \"d\"    diff-map)\n     (define-key map \"=\"   'git-diff-file)\n     (define-key map \"f\"   'git-find-file)\n@@ -1362,6 +1432,8 @@ Return the list of files that haven't been handled.\"\n     (define-key map \"x\"   'git-remove-handled)\n     (define-key map \"\\C-?\" 'git-unmark-file-up)\n     (define-key map \"\\M-\\C-?\" 'git-unmark-all)\n+    ; the commit submap\n+    (define-key commit-map \"\\C-a\" 'git-amend-commit)\n     ; the diff submap\n     (define-key diff-map \"b\" 'git-diff-file-base)\n     (define-key diff-map \"c\" 'git-diff-file-combined)\n-- \n1.5.4.38.g0d380\n\n-- \nAlexandre Julliard\njulliard@winehq.org\n"},{"id":"67795","messageId":"87prv8294k.fsf@osv.gnss.ru","threadId":"11939","inReplyTo":"87ve51orq8.fsf@wine.dyndns.org","subject":"Re: [PATCH 2/4] git.el: Added a command to amend a commit.","fromName":"Sergei Organov","fromEmail":"osv@javad.com","sentAt":"2008-02-07T13:23:23Z","receivedAt":"2008-02-07T13:23:23Z","isPatch":true,"sender":{"key":"osv@javad.com","avatar":null},"body":"Alexandre Julliard <julliard@winehq.org> writes:\n\n> It reverts the commit and sets up the status and edit log buffer to\n> allow making changes and recommitting it. Bound to C-c C-a.\n\nNice! Doesn't it lack something like this:\n\ndiff --git a/contrib/emacs/git.el b/contrib/emacs/git.el\nindex c3c0c45..9ad37a1 100644\n--- a/contrib/emacs/git.el\n+++ b/contrib/emacs/git.el\n@@ -1385,6 +1385,7 @@ Return the list of files that haven't been handled.\"\n     `(\"Git\"\n       [\"Refresh\" git-refresh-status t]\n       [\"Commit\" git-commit-file t]\n+      [\"Ammend Commit\" git-ammend-commit t]\n       (\"Merge\"\n \t[\"Next Unmerged File\" git-next-unmerged-file t]\n \t[\"Prev Unmerged File\" git-prev-unmerged-file t]\n\n-- Sergei.\n"},{"id":"67799","messageId":"86bq6suc79.fsf@lola.quinscape.zz","threadId":"11939","inReplyTo":"87prv8294k.fsf@osv.gnss.ru","subject":"Re: [PATCH 2/4] git.el: Added a command to amend a commit.","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2008-02-07T13:29:30Z","receivedAt":"2008-02-07T13:29:30Z","isPatch":true,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Sergei Organov <osv@javad.com> writes:\n\n> Alexandre Julliard <julliard@winehq.org> writes:\n>\n>> It reverts the commit and sets up the status and edit log buffer to\n>> allow making changes and recommitting it. Bound to C-c C-a.\n>\n> Nice! Doesn't it lack something like this:\n>\n> diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el\n> index c3c0c45..9ad37a1 100644\n> --- a/contrib/emacs/git.el\n> +++ b/contrib/emacs/git.el\n> @@ -1385,6 +1385,7 @@ Return the list of files that haven't been handled.\"\n>      `(\"Git\"\n>        [\"Refresh\" git-refresh-status t]\n>        [\"Commit\" git-commit-file t]\n> +      [\"Ammend Commit\" git-ammend-commit t]\n>        (\"Merge\"\n>  \t[\"Next Unmerged File\" git-next-unmerged-file t]\n>  \t[\"Prev Unmerged File\" git-prev-unmerged-file t]\n\n\"amend\", please.\n\n-- \nDavid Kastrup\n"}]}