#!/usr/bin/env bash ### update_autogen - update some auto-generated files in the Emacs tree ## Copyright (C) 2011-2022 Free Software Foundation, Inc. ## Author: Glenn Morris ## Maintainer: emacs-devel@gnu.org ## 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 is a helper script to update some generated files in the Emacs ## repository. This is suitable for running from cron. ## Only Emacs maintainers need use this, so it uses bash features. ## ## By default, it updates the versioned loaddefs-like files in lisp, ## except ldefs-boot.el. ### Code: die () # write error to stderr and exit { [ $# -gt 0 ] && echo "$PN: $@" >&2 exit 1 } PN=${0##*/} # basename of script PD=${0%/*} [ "$PD" = "$0" ] && PD=. # if PATH includes PWD ## This should be the admin directory. cd $PD || exit cd ../ [ -d admin ] || die "Could not locate admin directory" [ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1 || die "Not in a git repository" usage () { cat 1>&2 < /dev/null' EXIT while getopts ":hcfqA:CL" option ; do case $option in (h) usage ;; (c) commit=1 ;; (f) force=1 ;; (q) quiet=1 ;; (A) autogendir=$OPTARG [ -d "$autogendir" ] || die "No autogen directory: $autogendir" ;; (C) clean=1 ;; (L) lboot_flag=1 ;; (\?) die "Bad option -$OPTARG" ;; (:) die "Option -$OPTARG requires an argument" ;; (*) die "getopts error" ;; esac done shift $(( --OPTIND )) OPTIND=1 ## Does not work 100% because a lot of Emacs batch output comes on stderr (?). [ "$quiet" ] && exec 1> /dev/null ## Run status on inputs, list modified files on stdout. status () { git status -s "$@" >| $tempfile || die "git status error for $@" local stat file modified while read stat file; do [ "$stat" != "M" ] && \ die "Unexpected status ($stat) for generated $file" modified="$modified $file" done < $tempfile echo "$modified" return 0 } # function status echo "Checking input file status..." ## The lisp portion could be more permissive, eg only care about .el files. modified=$(status ${autogendir:+$sources} ${ldefs_flag:+lisp}) || die [ "$modified" ] && { echo "Locally modified: $modified" [ "$force" ] || die "There are local modifications" } ## Probably this is overkill, and there's no need to "bootstrap" just ## for making autoloads. [ "$clean" ] && { echo "Running 'make maintainer-clean'..." make maintainer-clean #|| die "Cleaning error" rm -f $ldefs_in } echo "Running autoreconf..." autoreconf ${clean:+-f} -i -I m4 2>| $tempfile retval=$? ## Annoyingly, autoreconf puts the "installing `./foo' messages on stderr. if [ "$quiet" ]; then grep -v 'installing `\.' $tempfile 1>&2 else cat "$tempfile" 1>&2 fi [ $retval -ne 0 ] && die "autoreconf error" ## Uses global $commit. commit () { local type=$1 shift [ $# -gt 0 ] || { echo "No files were modified" return 0 } echo "Modified file(s): $@" [ "$commit" ] || return 0 echo "Committing..." git commit -m "; Auto-commit of $type files." "$@" || return $? ## In case someone else pushed something while we were working. git pull --rebase || return $? git push || return $? echo "Committed files: $@" } # function commit [ "$autogendir" ] && { cp $genfiles $autogendir/ cd $autogendir || die "cd error for $autogendir" echo "Checking status of generated files..." modified=$(status $basegen) || die commit "generated" $modified || die "commit error" exit 0 } # $autogendir [ "$ldefs_flag" ] || exit 0 echo "Finding loaddef targets..." find lisp -name '*.el' -exec grep '^;.*generated-autoload-file:' {} + | \ sed -e '/loaddefs\|esh-groups/d' -e 's|/[^/]*: "|/|' -e 's/"//g' \ >| $tempfile || die "Error finding targets" genfiles= while read genfile; do ## Or we can just use sort -u when making tempfile... case " $genfiles " in *" $genfile "*) continue ;; esac [ -r $genfile ] || die "Unable to read $genfile" genfiles="$genfiles $genfile" done < $tempfile [ "$genfiles" ] || die "Error setting genfiles" [ -e Makefile ] || { echo "Running ./configure..." ## Minimize required packages. ./configure --without-x || die "configure error" } ## Build the minimum needed to get the autoloads. echo "Running lib/ make..." make -C lib "$@" all || die "make lib error" echo "Running src/ make..." make -C src "$@" bootstrap-emacs || die "make src error" echo "Running lisp/ make..." make -C lisp "$@" autoloads EMACS=../src/bootstrap-emacs || die "make src error" ## Ignore comment differences. [ ! "$lboot_flag" ] || \ diff -q -I '^;' $ldefs_in $ldefs_out || \ cp $ldefs_in $ldefs_out || die "cp ldefs_boot error" # Refresh the prebuilt grammar-wy.el grammar_in=lisp/cedet/semantic/grammar-wy.el grammar_out=lisp/cedet/semantic/grm-wy-boot.el make -C admin/grammars/ ../../$grammar_in cp $grammar_in $grammar_out || die "cp grm_wy_boot error" echo "Checking status of loaddef files..." ## It probably would be fine to just check+commit lisp/, since ## making autoloads should not effect any other files. But better ## safe than sorry. modified=$(status $genfiles $ldefs_out $grammar_out) || die commit "loaddefs" $modified || die "commit error" exit 0 ### update_autogen ends here