From: Eshel Yaron Date: Fri, 22 Dec 2023 18:08:49 +0000 (+0100) Subject: ; * admin/cherry.el: New file. X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=423908c150772e5ea459473d9a96febed71b4131;p=emacs.git ; * admin/cherry.el: New file. Add helper command 'cherry-pick-new-commits' for interactively cherry-picking new commits from the upstream master branch. --- diff --git a/admin/cherry-skip-list b/admin/cherry-skip-list new file mode 100644 index 00000000000..912d2308ca7 --- /dev/null +++ b/admin/cherry-skip-list @@ -0,0 +1,17 @@ +5f923ff1a6a8a9ff6f06dc49c8e0e2ceee111567 +945aa0e42bc08879a9c979cbffb9b3f50e4945f3 +8e52a59808e9ca1b8e535725eb76b83e409745eb +22b2390c66e2f9a5f3bcb2f1727c830348a6e61d +7a7491a23eacaae41c07568d833e668ec1d351cf +598ab9ca10d35d6990f9af3a4d58f265acd8b121 +8e0882d17a38cb9d309df705e76a8e88529f30a9 +46367e0a5c9a58087d59f19966b23ee980bdbb24 +67e16d37e9c83fea9f67d144eeac27a83d52c949 +73acd543cb1f88af880445de1e1a7238dd46c9de +b499d4f65a7c1ce45500dcbf1c5c63d85241b330 +2e5d50ee43096ff5422c88f835ccceb1728def06 +3aa9fbf4fab2f21c0a6f0dba510bfe8266578f2f +7058988fd65d719b69b658a74b268d4a2f1909c5 +4239c27f3867b558ae2e26950d5153d496b02d8f +91f2ade57bb72e9bb4a44da44e5dc69adb3c7584 +93592c69179a8d5ccf1f09c3f26e91f194772b8e diff --git a/admin/cherry.el b/admin/cherry.el new file mode 100644 index 00000000000..ffcdcd70ada --- /dev/null +++ b/admin/cherry.el @@ -0,0 +1,112 @@ +;;; cherry.el --- Cherry pick commits from upstream master -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 of the License, or +;; (at your option) any later version. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Commentary: + +;; This library defines the command `cherry-pick-new-commits' that +;; iterates over new commits in the upstream master branch, and +;; suggests cherry-picking them one after the other. + +;;; Code: + +(defvar cherry-upstream-remote "upstream") + +(defvar cherry-upstream-branch "master") + +(defvar cherry-skip-list-file + (expand-file-name "admin/cherry-skip-list" source-directory)) + +(defun cherry-merge-base () + (car + (string-lines + (shell-command-to-string + (concat "git -C " source-directory " merge-base " + cherry-upstream-remote "/" cherry-upstream-branch + " HEAD")) + t))) + +(defun cherry-picked-p (commit merge-base) + (car + (string-lines + (shell-command-to-string + (concat "git log -1 --pretty=%H --grep='(cherry picked from commit " + commit + ")' " + merge-base "..HEAD")) + t))) + +(defun cherry-skipped-p (commit) + (= 0 (call-process "grep" cherry-skip-list-file nil nil + "-q" "-E" (concat "^" commit)))) + +(defun cherry-upstream-commits () + (string-lines + (shell-command-to-string + (concat "git -C " source-directory " cherry HEAD upstream/master | grep -vE '^-' | cut -f 2 -d ' '")) + t)) + +(defun cherry-pick-new-commits () + "Pick or skip new commits in the upstream branch." + (interactive) + (call-process "git" nil nil nil + "-C" source-directory "fetch" cherry-upstream-remote) + (let* ((merge-base (cherry-merge-base)) + (new-commits + (seq-remove + (lambda (commit) + (or (cherry-picked-p commit merge-base) + (cherry-skipped-p commit))) + (cherry-upstream-commits)))) + (if new-commits + (dolist (commit new-commits) + (with-current-buffer (get-buffer-create "*cherry*") + (delete-region (point-min) (point-max)) + (fundamental-mode)) + (call-process "git" nil "*cherry*" t "-C" source-directory + "format-patch" "-1" commit "--stdout") + (pop-to-buffer "*cherry*") + (diff-mode) + (goto-char (point-min)) + (let ((choice (read-multiple-choice + "Pick?" + '((?p "pick") + (?s "skip") + (?q "quit") + ;; (?a "amend") + )))) + (pcase (car choice) + (?s + (message "Skipping...") + (shell-command (concat "echo " commit + (read-string "Reason: " "") + ">>" cherry-skip-list-file)) + (message "Skipped.")) + (?p + (message "Picking...") + (if (= 0 (call-process "git" nil nil nil + "-C" source-directory + "cherry-pick" "-x" commit)) + (message "Picked.") + (user-error "Cherry picking failed"))) + (?q (bury-buffer "*cherry*") + (user-error "Quit cherry picking"))))) + (message "No new commits.")))) + +(provide 'cherry) +;;; cherry.el ends here