Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 181 additions & 18 deletions bin/git-ignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)

# awk script that takes 2 input files. The first one is newline deilmeted
# string of patterns to look for, second one is the file to remove them from.
# outfile has to be passed with -v upon call and is the file result is
# written to.
read -r -d '' AWK_SCRIPT <<'EOF'
# process the first "file" (newline split argument list)
NR==FNR { a[b++]=$0; next; }
# process file
{
found=0;
for (i=0; i != b; i++) {
if (a[i] == $0) { found=1; }
}
if (found == 1) { print "... removing '"$0"'"; }
else { print $0 > outfile }
}
EOF



show_contents() {
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
Expand Down Expand Up @@ -94,29 +114,172 @@ add_patterns() {
done
}

edit_file() {
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
echo "Editing $1 gitignore: ($2)" && eval "$(git var GIT_EDITOR) $(printf '%q' "$file")"
echo "Done."
else
echo "There is no $1 .gitignore yet." >&2
exit 1
fi
}

_usage() {
cat << EOF
Usage: git ignore [OPTION]... [PATTERN]...
Modify or display local global or private gitignore files.

OPTIONs set context (local, global, private) and action (display, add,
remove, edit). In case of collision, last flag overwrites preceding ones.
Defaults are: local context, action is display (see man git ignore for
more details).
Context examples:
local: .../repo/.gitignore
private: .../repo/.git/info/exclude
global: \$HOME/.gitignore

PATTERNs are the gitignore patterns as specified in git documentation.

Options:
-l, --local Set context to local gitignore
-g, --global Set context to global gitignore
-p, --private Set context to private gitignore
-e, --edit Set action to edit
-r, --remove Set action to remove
-h, --help Print this message
-- End of options delimiter
EOF
}

remove_patterns() {
declare -a args
local tmpfile
args=( "${@:3}" )
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
tmpfile="$(mktemp -q "${TMPDIR:-/tmp}"/git-extras-ignore.XXXXXX 2>/dev/null)"
echo "Removing patterns from $1 gitignore: $2"
Comment thread
spacewander marked this conversation as resolved.
awk -v outfile="$tmpfile" "${AWK_SCRIPT}"\
<(printf '%s\n' "${args[@]}") "$file"
cat "$tmpfile" > "$file"
rm "$tmpfile"
else
echo "There is no $1 .gitignore yet"
exit 1
fi
}


# can have only 1 action and 1 level, if conflicting flags are passed
# latter ones overwrite former
# sanity of args not tested (e.g. there should be no args if -e is supplied)
if test $# -eq 0; then
show_global
echo "---------------------------------"
show_local
echo "---------------------------------"
show_private
else
case "$1" in
-l|--local)
test $# -gt 1 && add_local "${@:2}" && echo
show_local
;;
-g|--global)
test $# -gt 1 && add_global "${@:2}" && echo
show_global
;;
-p|--private)
test $# -gt 1 && add_private "${@:2}" && echo
show_private
;;
*)
add_local "$@"
;;
esac
fi
# parse flags and args
level="none"
action="none"
declare -a args
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
_usage
exit 0
;;
-l|--local)
level="local"
;;
-g|--global)
level="global"
;;
-p|--private)
level="private"
;;
-e|--edit)
action="edit"
;;
-r|--remove)
action="remove"
;;
--)
shift
args+=("$@")
break
;;
*)
args+=("$1")
;;
esac
shift
done
# compatible with previous version
if [ "$action" = "none" ]; then
case "$level" in
local)
test ${#args[@]} -ne 0 && add_local "${args[@]}" && echo
show_local
;;
global)
test ${#args[@]} -ne 0 && add_global "${args[@]}" && echo
show_global
;;
private)
test ${#args[@]} -ne 0 && add_private "${args[@]}" && echo
show_private
;;
none)
add_local "${args[@]}"
# maybe show_local here too?
;;
esac
exit 0
# open file in editor
elif [ "$action" = "edit" ]; then
case "$level" in
local|none)
cd_to_git_root --warn
edit_file 'local' .gitignore && echo
;;
global)
global_gitignore="$(global_ignore)"
edit_file global "$global_gitignore" && echo
;;
private)
cd_to_git_root --error
test -d "${GIT_DIR}/info" || mkdir -p "${GIT_DIR}/info"
edit_file private "${GIT_DIR}/info/exclude" && echo
;;
esac
exit 0
# remove entries
else
if [ ${#args[@]} -eq 0 ]; then
echo "Nothing to remove."
exit 0
fi
case "$level" in
local|none)
cd_to_git_root --warn
remove_patterns 'local' .gitignore "${args[@]}" && echo
show_local
;;
global)
global_gitignore="$(global_ignore)"
remove_patterns global "$global_gitignore" "${args[@]}" && echo
show_global
;;
private)
cd_to_git_root --error
remove_patterns private "${GIT_DIR}/info/exclude" "${args[@]}" && echo
show_private
;;
esac
exit 0

fi
fi
4 changes: 2 additions & 2 deletions etc/bash_completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ _git_graft(){
_git_ignore(){
case "$cur" in
--*)
__gitcomp "--global --local --private"
__gitcomp "--global --local --private --edit --remove"
return
;;
-*)
__gitcomp "--global --local --private -g -l -p"
__gitcomp "--global --local --private --edit --remove -g -l -p -e -r"
return
;;
esac
Expand Down
10 changes: 6 additions & 4 deletions etc/git-extras-completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,11 @@ _git-guilt() {

_git-ignore() {
_arguments -C \
'(--local -l)'{--local,-l}'[show local gitignore]' \
'(--global -g)'{--global,-g}'[show global gitignore]' \
'(--private -p)'{--private,-p}'[show repo gitignore]' \
'(--local -l)'{--local,-l}'[set context to local gitignore]' \
'(--global -g)'{--global,-g}'[set context to global gitignore]' \
'(--private -p)'{--private,-p}'[set context to private gitignore]' \
'(--edit -e)'{--edit,-e}'[set action to edit]' \
'(--remove -r)'{--remove,-r}'[set action to remove]' \
'*:filename:_files'
}

Expand Down Expand Up @@ -443,7 +445,7 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
graft:'merge and destroy a given branch' \
guilt:'calculate change between two revisions' \
ignore-io:'get sample gitignore file' \
ignore:'add .gitignore patterns' \
ignore:'Modify or display .gitignore files' \
info:'returns information on current repository' \
local-commits:'list local commits' \
lock:'lock a file excluded from version control' \
Expand Down
10 changes: 6 additions & 4 deletions etc/git-extras.fish
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ set __fish_git_extras_commands \
"graft:Merge and destroy a given branch" \
"guilt:calculate change between two revisions" \
"ignore-io:Get sample gitignore file" \
"ignore:Add .gitignore patterns" \
"ignore:Modify or display .gitignore files" \
"info:Returns information on current repository" \
"local-commits:List local commits" \
"lock:Lock a file excluded from version control" \
Expand Down Expand Up @@ -162,9 +162,11 @@ complete -c git -f -n '__fish_git_using_command guilt' -s e -l email -d 'display
complete -c git -f -n '__fish_git_using_command guilt' -s d -l debug -d 'output debug information'
complete -c git -f -n '__fish_git_using_command guilt' -s h -d 'output usage information'
# ignore
complete -c git -f -n '__fish_git_using_command ignore' -s l -l local -d 'show local gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s g -l global -d 'show global gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s p -l private -d 'show repo gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s l -l local -d 'set context to local gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s g -l global -d 'set context to global gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s p -l private -d 'set context to private gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s e -l edit -d 'set action to edit'
complete -c git -f -n '__fish_git_using_command ignore' -s r -l remove -d 'set action to remove'
# ignore-io
function __fish_git_extra_get_ignore_io_types
# we will first remove every tab spaces, and then append `\t` at the end to remove the default description
Expand Down
2 changes: 1 addition & 1 deletion man/git-extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ git-extras(1) -- Awesome GIT utilities
- **git-graft(1)** Merge and destroy a given branch
- **git-guilt(1)** calculate change between two revisions
- **git-ignore-io(1)** Get sample gitignore file
- **git-ignore(1)** Add .gitignore patterns
- **git-ignore(1)** Modify or display .gitignore files
- **git-info(1)** Returns information on current repository
- **git-local-commits(1)** List local commits
- **git-lock(1)** Lock a file excluded from version control
Expand Down
Loading
Loading