Skip to content

Added edit/remove functionality to git-ignore#1258

Open
kdergachev wants to merge 4 commits into
tj:mainfrom
kdergachev:main
Open

Added edit/remove functionality to git-ignore#1258
kdergachev wants to merge 4 commits into
tj:mainfrom
kdergachev:main

Conversation

@kdergachev
Copy link
Copy Markdown

PR for issue #1257

These commits introduce flags -r/--remove and -e/--edit to git-ignore to allow removing patterns the same way they can be added and for opening ignore files in a text editor. Some other minor changes like '--' flag-argument separator introduced. New version is mostly backwards-compatible with old one.

Some quirks/things to consider:

  • Flags for actions/locations override each other and the last is the actual one.
  • Temporary file creation for remove (found that filling tmp file with double loop over lines and patterns is the best way to remove a list of patterns while not interpreting patterns as regex or any other type of special symbols, maybe there is a better way)
  • Should edit action create a file if one does not exist?
  • Unnecessary arguments are not checked for and just omitted

Submitting this as a draft, and if everything's OK/after changes are made will modify documentation accordingly (same for output with -h/--help flags).

Copy link
Copy Markdown
Collaborator

@spacewander spacewander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update the docs, and completion script in https://github.com/tj/git-extras/tree/main/etc (if possible)

Comment thread bin/git-ignore
}

_usage() {
# TODO
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's either fulfill it or drop it

Comment thread bin/git-ignore Outdated
level="none"
action="none"
declare -a args
while [ "$1" != "" ]; do
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It breaks documented empty-string patterns. while [ "$1" != "" ] stops parsing as soon as a pattern is "", so existing examples like git ignore --local "" "# Temporary files" no longer add anything after the empty argument. Use while [ $# -gt 0 ] instead.

Comment thread bin/git-ignore Outdated
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
echo "Removing patterns from $1 gitignore ($2)..."
while read -r line; do
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can corrupt preserved lines during remove. read without IFS= trims leading/trailing whitespace, echo "$line" mishandles values like -n, and the loop skips a final line without a trailing newline. Use while IFS= read -r line || [ -n "$line" ]; do and printf '%s\n' "$line".

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While thinking about these issues found that perl has \E \Q escapes. These could work too (something like perl -pe "s/\Q${pattern1}\E\n?//; s/\Q${pattern2}\E\n?//; ..."). Which of the approaches do you think is better?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we have to add perl in https://github.com/tj/git-extras/blob/main/Installation.md#dependencies. Could it be solved with awk or sed?

Comment thread bin/git-ignore Outdated
edit_file() {
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
echo "Editing $1 gitignore ($2)..." && $(git var GIT_EDITOR) "$file"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$(git var GIT_EDITOR) "$file" loses shell quoting for editor values like vim -c 'set ft=gitignore', and echo "Done." still runs even if the editor exits non-zero.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the line to use eval - it seems to fix this issue.

Comment thread bin/git-ignore Outdated
tmpfile="$(mktemp -q "${TMPDIR:-/tmp}"/git-extras-ignore.XXXXXX 2>/dev/null)"
else
cd_to_git_root --warn &>/dev/null
tmpfile="$(mktemp -q "$GIT_DIR"/git-extras-ignore.XXXXXX 2>/dev/null)"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we always put the temp file in $TMPDIR?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wanted it to work the same way git does and it writes its tmp files in .git. Changed to always use global tmp directory.

Comment thread bin/git-ignore Outdated
echo "Removed $line pattern."
fi
done < "$file"
mv "$tmpfile" "$file" # tmp file created in get_tmp_file 'deleted'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If .gitignore or the global ignore file is a symlink, mv "$tmpfile" "$file" replaces the symlink instead of updating its target; it can also lose file metadata. Can we update it in place?

…ndling, tmp file location, symlinked gitignore handling).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants