FR: Allow placing temporary description files within the related repository directory tree
Problem
Per discussion in the "Jujutsu" Discord server's "chat" channel, as of #6403, jj describe creates temporary files to capture the change description under the user's temporary directory, instead of within a directory dominated by the related VCS repository's root directory.
When trying to use the Emacs magit package's git-commit-mode facility together with using emacsclient as the editor, git-commit-mode fails to initialize properly because it notices that the temporary file that the containing buffer is visiting does not lie within a Git repository, per magit/magit#5372.
At present, it is not easy—and maybe not feasible—to adjust magit's behavior to accommodate this discrepancy.
Proposed Solution
Introduce a configuration parameter honored by the jj describe command that would direct it to create these temporary files within the related VCS repository's directory tree, such as under .jj/repo as it used to do before #6403.
Alternatives Considered
I'd like to configure magit to force it to not bother trying to consult with the git command to learn about the changed staged for the pending commit, as that's help that I don't need for my use with jj describe. For now, though, that doesn't appear to be possible.
If we don't want to introduce a configuration option for this, adding a command-line flag to jj describe would also be good enough, whether telling it to use a particular directory path or toggling a Boolean value to switch it back into its old mode of choosing a path within the VCS repository.
It might also be possible to write a short shell program around emacsclient that would create a symbolic link from within the VCS directory tree to the temporary file that jj describe creates, if magit is willing to use a symbolic link's path without following the link to its target first.
@martinvonz mentioned that jj describe should probably set the "GIT_DIR" environment variable in a colocated repository too, but as described in magit/magit#5100, that won't help people who use emacsclient as their editor, since the Emacs process to which emacsclient connects won't see that environment variable binding.
Additional Context
I do think that #6403's behavior is preferable in general, and should be the default choice.
I wrote the following program in haste to use as a wrapper for emacsclient, nominated as the "ui.editor" value in my jujutsu configuration:
emacsclient-for-jj shell program
#!/usr/bin/env bash
# See the following GitHub issues and discussions for the motivation for this program:
# - https://github.com/jj-vcs/jj/issues/6540
# - https://github.com/magit/magit/discussions/5372
set -e -u -o pipefail
function usage() {
printf "usage: %s [-h] description_file\n" "$(basename "${0}")" 1>&2
exit 2
}
function parse_args() {
while getopts h name
do
case "${name}" in
h) usage;;
?) usage;;
esac
done
}
parse_args "$@"
shift $((OPTIND - 1))
if (( $# != 1 )); then
printf "%s: expected one argument\n" "$(basename "${0}")" 1>&2
exit 2
fi
target_file="$1"
shift
if [ -z "${target_file}" ]; then
printf "%s: description file must not be empty\n" "$(basename "${0}")" 1>&2
exit 2
fi
workspace_repo_dir="$(jj workspace root)/.jj/repo"
if [ -f "${workspace_repo_dir}" ]; then
# We're in a non-initial Jujutsu workspace, where instead of there
# being a directory with the expected path, there's a regular file
# whose content points back to the repository's initial workspace.
workspace_repo_dir="$(cat "${workspace_repo_dir}")"
elif ! [ -e "${workspace_repo_dir}" ]; then
echo >&2 "Jujutsu workspace repository directory ${workspace_repo_dir} does not exist."
exit 1
elif ! [ -d "${workspace_repo_dir}" ]; then
echo >&2 "Jujutsu workspace repository directory entry ${workspace_repo_dir} is not a directory."
exit 1
fi
target_file_basename="$(basename "${target_file}")"
# Ensure that the file name that Emacs sees ends with a sentinel
# extension in order to activate magit's "git-commit-mode"
# automatically, per the "git-commit-filename-regexp" Emacs variable.
if [[ ! "${target_file_basename}" =~ .+\.jjdescription$ ]]; then
target_file_basename+=".jjdescription"
fi
link_path="${workspace_repo_dir}/${target_file_basename}"
ln -s "${target_file}" "${link_path}"
trap 'rm -rf "${link_path}"' EXIT
emacsclient "${link_path}"
It pursues the idea of creating a symbolic link in the repository's .jj/repo directory pointing at the temporary file that jj describe creates.
It appears to work well enough for now. However, it does feel like an undue burden to have to write such a thing.
I thought of what I think is a nice solution here: https://github.com/jj-vcs/jj/discussions/6794