From b4adeea21740d94cab6e0061aabf22c4ee151618 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Fri, 28 Oct 2022 23:22:22 -0700 Subject: replace emacs.git workstation integration commit Also attempt to improve readability & commenting in wrapper script. Archival copy of the workstation integration commit we're replacing: Date: Sat, 25 Dec 2021 18:05:21 -0700 Subject: Workstation integration of personal development builds branch --- admin/flagfile.melete | 0 lib-src/emacsclient.c | 7 +++++-- lisp/emacs-lisp/package.el | 1 + lisp/startup.el | 7 ++++++- 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 admin/flagfile.melete diff --git a/admin/flagfile.melete b/admin/flagfile.melete new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 425db8cface..62d71559d3c 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -1794,7 +1794,10 @@ start_daemon_and_retry_set_socket (void) } else { - char emacs[] = "emacs"; + const char *devel_build_rel = "/src/emacs/src/emacs"; + char *emacs = xmalloc (strlen (egetenv ("HOME")) + + strlen (devel_build_rel) + 1); + strcpy ( stpcpy (emacs, egetenv ("HOME")), devel_build_rel); char daemon_option[] = "--daemon"; char *d_argv[3]; d_argv[0] = emacs; @@ -1811,7 +1814,7 @@ start_daemon_and_retry_set_socket (void) d_argv[1] = daemon_arg; } # endif - execvp ("emacs", d_argv); + execvp (emacs, d_argv); message (true, "%s: error starting emacs daemon\n", progname); exit (EXIT_FAILURE); } diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index d619142d64c..d464e120193 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -312,6 +312,7 @@ package-directory-list (and (stringp f) (equal (file-name-nondirectory f) "site-lisp") (push (expand-file-name "elpa" f) result))) + (push "/usr/share/emacs-snapshot/site-lisp/elpa" result) (nreverse result)) "List of additional directories containing Emacs Lisp packages. Each directory name should be absolute. diff --git a/lisp/startup.el b/lisp/startup.el index 725984b815b..e10d854c368 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -1452,7 +1452,12 @@ command-line ;; be loaded from site-run-file and wants to test if -q was given ;; should check init-file-user instead, since that is already set. ;; See cus-edit.el for an example. - (if site-run-file + (when site-run-file + (let ((file "/etc/emacs/site-start.d/00debian.el")) + ;; When the Emacs build invokes Emacs, such as in the + ;; Makefile rule for ${unidir}/emoji-labels.el, 00debian.el + ;; might not exist. Should be fine to just skip the load. + (when (file-readable-p file) (load file))) ;; Sites should not disable the startup screen. ;; Only individuals should disable the startup screen. (let ((inhibit-startup-screen inhibit-startup-screen)) --- .emacs.d/early-init.el | 14 ++++ bin/emacsclient | 179 ++++++++++++++++++++++++------------------------- lib-src/mr/config | 63 +++++++++-------- 3 files changed, 137 insertions(+), 119 deletions(-) diff --git a/.emacs.d/early-init.el b/.emacs.d/early-init.el index c3d67b50..23f3c6a2 100644 --- a/.emacs.d/early-init.el +++ b/.emacs.d/early-init.el @@ -5,6 +5,20 @@ ;; Released under the terms of the GNU GPL as published by the FSF; either ;; version 3, or (at your option) any later version. +(when (file-in-directory-p invocation-directory (expand-file-name "~/")) + ;; Make packages compiled against my emacs-snapshot Debian packages + ;; available to in-tree builds too. (Used to do this by patching the code + ;; computing the default value of `package-directory-list' in those builds.) + (when (file-directory-p "/usr/share/emacs-snapshot/site-lisp/elpa") + (add-to-list 'package-directory-list + "/usr/share/emacs-snapshot/site-lisp/elpa" t)) + + ;; Run Debian's site-start library site-run-file for in-tree builds too. + ;; (Used to do this by patching `command-line' in those builds.) + (when (file-readable-p "/etc/emacs/site-start.d/00debian.el") + (load "/etc/emacs/site-start.d/00debian.el"))) + + ;;; Per docstring for `after-make-frame-functions', these additions to that ;;; list of functions are made in this file in order that they can affect the ;;; initial frame. diff --git a/bin/emacsclient b/bin/emacsclient index b4a2238b..1ac1b993 100755 --- a/bin/emacsclient +++ b/bin/emacsclient @@ -28,8 +28,9 @@ want_eval=false want_version=false devel_running=false installed_running=false -pass_to_gdbmacs=false -status= +make= +branch= +gud_status= daemon_name= gdbmacs= args= @@ -64,10 +65,14 @@ spw_flock () { fi } -die_wedged () { - maybe_notify "in-tree Emacs appears to be wedged" - # Only exit non-zero if we were expected to start the daemon. - ! $may_start; exit +pass_to_gdbmacs () { + if $want_eval || $want_update; then + maybe_notify "in-tree Emacs appears to be wedged" + # Only exit non-zero if we were expected to start the daemon. + ! $may_start; exit + else + exec "$installed_emacsclient" -sgdbmacs "$@" 3>&- 4>&- + fi } egrep_negate () { @@ -115,7 +120,8 @@ if [ -n "$listener" ]; then esac fi -# ---- Special case for primary session that's always under gdb +# Make it possible, with primary session, to quickly replace in-tree Emacs +# with installed Emacs. See 'C-i E' Sway/i3 binding. if [ -z "$daemon_name" ] && $devel_running && $want_installed; then inotifywait -qq -e delete "$socket" & inotifywait=$! @@ -133,88 +139,90 @@ if [ -z "$daemon_name" ] && $devel_running && $want_installed; then (gud-basic-call "quit")))))' wait $inotifywait + listener= devel_running=false fi -# ---- End special case for primary session that's always under gdb [ -z "$listener" ] && ! $may_start && ! $want_version && exit 0 -# We check whether there is something which looks like the installed Emacs -# running because we do not want the in-tree emacsclient to try to connect to -# that, and we check whether there is a build in progress and no running -# daemon, as we don't want to start a new daemon until the build is finished. -# The idea is that I can always hit C-i e without worrying about builds. +# We start up an in-tree Emacs daemon only when a branch named after this host +# is checked out, packages compiled against my emacs-snapshot Debian packages +# are available, and there isn't a build still in progress -- avoids having to +# consider whether a build is in progress when hitting 'C-i e'. +# +# The purpose of a branch for localhost is to keep track of what upstream +# commit we want to be running on this host (e.g. emacs-29 vs. master), and +# for WIP commits. It doesn't usually need to be pushed anywhere. +# +# We also examine $installed_running here to avoid having the in-tree +# emacsclient(1) connect to the installed Emacs. + if ! $want_installed && ! $installed_running \ - && [ -e "$HOME/src/emacs/admin/flagfile.melete" \ - -a -x "$HOME/src/emacs/lib-src/emacsclient" \ - -a -d "/usr/share/emacs-snapshot/site-lisp/elpa" ] \ - && ! ( ! $devel_running && ps h -o pid -C make \ - | xargs pwdx 2>/dev/null \ - | grep -q "$HOME/src/emacs" ); then + && [ -x "$HOME/src/emacs/lib-src/emacsclient" \ + -a -d "/usr/share/emacs-snapshot/site-lisp/elpa" ]; then + make="$(ps h -o pid -C make)" + branch="$(git -C $HOME/src/emacs rev-parse --abbrev-ref HEAD)" +fi + +if [ "$branch" = "$(hostname -s)" ] \ + && ! ( ! $devel_running && [ -n "$make" ] \ + && echo "$make" | xargs pwdx \ + | grep -q "$HOME/src/emacs" ); then emacs="$devel_emacs" emacsclient="$devel_emacsclient" - - # ---- Two special cases for primary session that's always under gdb if [ -z "$daemon_name" ] && ! $want_version; then spw_flock 4 gdbmacs - # If devel Emacs is stopped or gdbmacs can't start it, ask gdbmacs to - # handle the request: it's probs. C-i e or editing a file via EDITOR. - [ -n "${gdbmacs:=$(get_listener ${socket_dir}gdbmacs)}" ] \ - && status=$("$installed_emacsclient" \ - -sgdbmacs \ - --eval \ - '(and (boundp '"'"'gud-comint-buffer) - (get-buffer-process gud-comint-buffer) - (string= "signal-received" - gdb-inferior-status))') - - if [ "$status" = t ]; then - if $want_eval || $want_update; then - die_wedged - else - pass_to_gdbmacs=true - fi - elif [ -z "$listener" ]; then - # inotifywait(1) in Debian "bullseye" doesn't have --include. - inotifywait -qq -e create "${socket_dir}" \ - --exclude "$(egrep_negate ${socket_dir}server)" & - inotifywait=$! - - if "$installed_emacsclient" \ - -a '' -sgdbmacs \ - --eval '(spw/gdbmacs-attach)' 3>&- 4>&-; then - wait $inotifywait - listener=true - elif $want_eval || $want_update; then - kill $inotifywait - die_wedged - else - kill $inotifywait - pass_to_gdbmacs=true - fi - fi - - if $pass_to_gdbmacs; then - emacs="$installed_emacs" - emacsclient="$installed_emacsclient" - socket="${socket_dir}gdbmacs" - listener="$gdbmacs" - set -- "$@" -sgdbmacs - fi - exec 4>&- + && gud_status=$("$installed_emacsclient" \ + -sgdbmacs \ + --eval \ + '(and (boundp '"'"'gud-comint-buffer) + (get-buffer-process gud-comint-buffer) + (string= "signal-received" + gdb-inferior-status))') fi - # ---- End two special cases for primary session that's always under gdb else emacs="$installed_emacs" emacsclient="$installed_emacsclient" fi -# Update Emacs daemon environment vars for a new interactive session. This -# allows us to have the Emacs daemon survive restarts of the graphical desktop -# environment, and to update Emacs on a remote host when there is a new -# forwarded SSH agent socket. See 'upenv' in .bash_defns. -if $want_update && [ -n "$listener" ]; then +# Except in the case above where ss(1) is not available, this wrapper script +# is responsible for starting up the daemon if it's not running. This is to +# ensure that only the in-tree emacsclient(1) talks to the in-tree Emacs, and +# only the installed emacsclient(1) talks to the installed Emacs. (We used to +# patch the in-tree emacsclient.c to only execute the in-tree Emacs, instead +# of handling it here.) + +if [ "$gud_status" = t ]; then + # Primary session is stopped. Ask gdbmacs to handle the request: it's + # probably C-i e or editing a file via EDITOR. + pass_to_gdbmacs "$@" +elif [ -z "$listener" ] && ! $want_version; then + if [ -z "$daemon_name" -a "$emacs" = "$devel_emacs" ]; then + # inotifywait(1) in Debian "bullseye" doesn't have --include. + inotifywait -qq -e create "${socket_dir}" \ + --exclude "$(egrep_negate ${socket_dir}server)" & + inotifywait=$! + # If gdbmacs fails to start main session, have gdbmacs handle the + # request; again, probably C-i e or editing via EDITOR. + if "$installed_emacsclient" \ + -a '' -sgdbmacs --eval '(spw/gdbmacs-attach)' 3>&- 4>&-; then + wait $inotifywait + else + kill $inotifywait + pass_to_gdbmacs "$@" + fi + else + "$emacs" --daemon"${daemon_name:+=$daemon_name}" 3>&- + fi +elif $want_update && ! $want_version; then + # Facility to update a (running) daemon's env for a new login session. + # This allows us to have the Emacs daemon survive restarts of the + # graphical desktop environment, and to update Emacs on a remote host when + # there is a new forwarded SSH agent socket. See 'upenv' in .bash_defns. + # + # --spw/update-environment may be combined with a regular request or be + # the only thing asked of this script. for var in DISPLAY WAYLAND_DISPLAY \ XAUTHORITY WINDOWID \ XDG_SESSION_TYPE XDG_CURRENT_DESKTOP \ @@ -232,21 +240,12 @@ if $want_update && [ -n "$listener" ]; then --eval "(spw/update-environment$args))" fi -maybe_hold_lock () { - # Hold on to the lock until daemon has started up. - $want_version || [ -n "$listener" ] \ - || inotifywait -qq -e create "${socket_dir}" \ - --exclude "$(egrep_negate $socket)" & -} - -# emacsclient(1) requires an argument. As a special case, if there are no -# arguments except -s/--socket-name, and no daemon is running, just start one. -# And if there were no arguments but we were requested just to update env -# vars, exit peacefully. -if [ "$#" -eq "$min_arg" -a -z "$listener" ]; then - maybe_hold_lock - exec "$emacs" --daemon"${daemon_name:+=$daemon_name}" 3>&- -elif ! ( [ "$#" -eq "$min_arg" ] && $want_update ); then - maybe_hold_lock - exec "$emacsclient" -a "" "$@" 3>&- -fi +# emacsclient(1) requires argument(s) beyond just -s/--socket-name. +# However, in the absence of any such arguments, if the daemon wasn't already +# running, or if --spw/update-environment, this wrapper starts the daemon if +# it wasn't already running, and exits zero. +# +# Note that if the daemon *was* already running and the only argument was +# -s/--socket-name, we do exec emacsclient(1) and it'll immediately exit. +[ "$#" -eq "$min_arg" ] && ( $want_update || [ -z "$listener" ] ) \ + || exec "$emacsclient" "$@" 3>&- 4>&- diff --git a/lib-src/mr/config b/lib-src/mr/config index fd2519cb..3bfe55f7 100644 --- a/lib-src/mr/config +++ b/lib-src/mr/config @@ -449,36 +449,31 @@ post_checkout = install-git-hooks pandoc-citeproc-preamble skip = lazy -# 'master' branch: just for installing changes to upstream master +# "master" branch: just for installing changes to upstream master # -# 'melete' branch: +# "$(hostname -s)" branch: # # Rebased onto sv.gnu.org's master branch. It has # -# - patch(es) to integrate these development builds with my Debian -# workstation setup, just enough that I can use these builds day-to-day; -# these assume a sufficiently recent emacs-snapshot package from demeter -# is installed, to provide /usr/share/emacs-snapshot/site-lisp/elpa -# # - bug fixes, reversions etc., (cleaned up versions of) which have not # yet made it onto sv.gnu.org's master, but which are required for my -# own usage +# own usage, on this machine or in general # # - WIP patches of my own -- this branch is used for my own development # work, at least where that doesn't require long-lived feature branches. # # A key advantage of using these development builds is that references to # files in *Help* buffers will be to ~/src/emacs, not to somewhere owned by -# root. The branch is named after my laptop at the time I first set it up. +# root. # -# 'athena/unstable' branch: +# "athena/unstable" branch: # # Merges from sv.gnu.org's master branch only. .deb packages produced from # this branch are available from . There are # two purposes: # # - providing byte-compiled Lisp /usr/share/emacs-snapshot/site-lisp/elpa -# to builds from the 'melete' branch +# to builds from the "$(hostname -s)" branch # # - direct use on machines other than my development laptop where I want # something more current than the stable release of Emacs but not with @@ -486,7 +481,7 @@ skip = lazy # # Updated only when new fixes, features or reversions on sv.gnu.org's # master branch are wanted on machines other than my development laptop. -# To do that, first 'melete' is updated using 'mr pull', and then I run +# To do that, first "melete" is updated using "mr pull", and then I run # that build for a day or so. Then # # % cd ~/src/emacs-snapshot @@ -511,10 +506,10 @@ skip = lazy # # It is important to test local installability of the new .deb, probably # in develacc or a sid chroot, before adding to demeter-apt, because -# running the rebased 'melete' branch doesn't detect any byte compilation +# running the rebased "melete" branch doesn't detect any byte compilation # issues against my current selection of elpa-* packages. # -# 'athena/CODENAME-bpo' branch: +# "athena/CODENAME-bpo" branch: # # Backported from athena/unstable. Automatically updated by # reprepro-rebuilder when updating athena/unstable as described above. @@ -527,31 +522,41 @@ post_checkout = cd emacs git remote add -f demeter demeter:emacs git remote add -f debian https://salsa.debian.org/rlb/deb-emacs.git/ - on spwhitton@melete && git checkout -b melete demeter/melete + # We might want a branch for localhost on non-workstations, but we only + # automatically create one on workstations. + if workstation; then + if [ -n "$(git for-each-ref '[r]efs/remotes/demeter/'$hostname)" ]; then + git checkout -b "$hostname" demeter/"$hostname" --no-track + else + git checkout -b "$hostname" --no-track + fi + fi ./autogen.sh all fixups = - git rev-parse melete@{upstream} >/dev/null 2>&1 \ - && git branch --unset-upstream melete + git rev-parse "$hostname"@{upstream} >/dev/null 2>&1 \ + && git branch --unset-upstream "$hostname" git config branch.master.rebase true - git config branch.melete.rebase true - git config branch.melete.pushRemote demeter + git config branch."$hostname".rebase true + # Set push remote in case we do need to make a backup of localhost's branch. + git config branch."$hostname".pushRemote demeter git config --replace-all remote.demeter.push ":" "^:$" - git config --replace-all remote.demeter.push "+melete:melete" "^\+melete:melete$" + git config --replace-all remote.demeter.push \ + "+${hostname}:${hostname}" "^\+${hostname}:${hostname}$" git config branch.deb/emacs/d/sid/master.dpmUpstreamBranch deb/emacs/d/sid/upstream git config branch.deb/emacs/d/sid/master.dpmPatchedBranch deb/emacs/d/sid/patched git config branch.deb/emacs-non-dfsg/d/sid/master.dpmUpstreamBranch \ deb/emacs-non-dfsg/d/sid/upstream git config branch.deb/emacs-non-dfsg/d/sid/master.dpmPatchedBranch \ deb/emacs-non-dfsg/d/sid/patched -# We don't have the melete branch's upstream set to origin/master to avoid -# accidentally pushing personal commits to Savannah (push.default cannot help -# here). So for convenient updates of melete to its conceptual upstream, we -# have this definition. "pull" not "update" because we want to update from -# upstream master deliberately, not as part of automated updates. -pull = git checkout melete \ - && git pull --rebase --autostash origin master \ - && git push -f demeter melete -skip = lazy || [ "$1" = pull ] && ! on spwhitton@melete +# We don't have the "$(hostname -s)" branch's upstream set to origin/master to +# avoid accidentally pushing personal commits to Savannah (push.default cannot +# help here). So for convenient updates of "$(hostname -s)" to its conceptual +# upstream, we have this definition. "pull" not "update" because we want to +# update from upstream master deliberately, not as part of automated updates. +pull = git checkout "$hostname" \ + && git pull --rebase --autostash origin master +skip = lazy || [ "$1" = pull ] \ + && [ -z "$(git for-each-ref '[r]efs/heads/'$hostname)" ] # myrepos git_status assumes a separate registration for each worktree. # Empty update action to prevent fetching from remotes over and over again. -- cgit v1.2.3