cogito: understand permissions written as "100755"
[cogito.git] / cg-rm
blobb8168cd0bad80819eb645f08ad4a5660b6e539fd
1 #!/usr/bin/env bash
3 # Remove files from the repository
4 # Copyright (c) Petr Baudis, 2005
6 # Takes a list of file names at the command line, and schedules them
7 # for removal from the GIT repository at the next commit. Those files
8 # are denoted by 'D' in the `cg-status` list. You can remove `cg-add`ed
9 # files to undo the addition; you can undo removals in an analogous way
10 # using `cg-add` and restore files deleted from the working copy using
11 # `cg-restore`.
13 # OPTIONS
14 # -------
15 # -a:: Remove all files which are gone from the working copy
16 # Record removal of all files which have been deleted from
17 # the working copy. Useful when there were some random files
18 # added/removed (e.g. by some third-party application) and you
19 # want to get the repository in sync: just use
20 # `cg-rm -a && cg-add -a`.
22 # -f:: Force removal of the physical files
23 # Also delete the files from the tree physically.
25 # -n:: Keep the physical files
26 # Do not delete the files from the tree physically, if they are
27 # still there. So it effectively just makes Cogito to stop caring
28 # about the file. This is the default.
30 # -r:: Remove files recursively
31 # If you pass cg-rm this flag and any directory names, it will try
32 # to remove files in those directories recursively.
34 # Testsuite: Partial (used in many tests but a dedicated testsuite is missing)
36 USAGE="cg-rm [-a] [-f] [-n] [-r] FILE..."
38 . "${COGITO_LIB}"cg-Xlib || exit 1
40 delete=
41 recursive=
42 rmgone=
43 while optparse; do
44 if optparse -f; then
45 delete=1
46 elif optparse -n; then
47 delete=
48 elif optparse -r; then
49 recursive=1
50 elif optparse -a; then
51 rmgone=1
52 else
53 optfail
55 done
57 [ -n "${ARGS[*]}" -o "$rmgone" ] || usage
59 TMPFILE="$(mktemp -t gitrm.XXXXXX)" || exit 1
60 TMPDIRFILE="$(mktemp -t gitrm.XXXXXX)" || exit 1
61 error=
62 non_existent=""
64 for file in "${ARGS[@]}"; do
65 absfile="$_git_relpath$file"
67 if [ ! -e "$absfile" ]; then
68 non_existent=" - not found, only recording removal"
71 if [ -d "$absfile" ]; then
72 if [ "$recursive" ]; then
73 echo "$file" >>"$TMPDIRFILE"
74 git-ls-files "$absfile" | while IFS=$'' read path; do
75 echo "${path#$_git_relpath}"
76 done >>"$TMPFILE"
77 else
78 echo "$file is a directory (use cg-rm -r?)" >&2
79 error=1
81 else
82 echo "$file" >>"$TMPFILE"
84 done
86 if [ "$rmgone" ]; then
87 (cd "$_git_relpath" && cg-status -s \! -n -w) >>"$TMPFILE"
88 if [ ! -s "$TMPFILE" ]; then
89 rm "$TMPFILE" "$TMPDIRFILE"
90 die "no files to remove"
94 cat "$TMPFILE" | sed -e 's/^/Removing file /' -e "s/\$/${non_existent}/"
95 if [ "$delete" ]; then (
96 cd "${_git_relpath:-.}"
97 cat "$TMPFILE" | tr '\n' '\0' | xargs -0 rm -f
98 [ -s "$TMPDIRFILE" ] && cat "$TMPDIRFILE" | tr '\n' '\0' | xargs -0 rmdir --ignore-fail-on-non-empty -p
99 ); fi
100 cat "$TMPFILE" | sed "s|^|$_git_relpath|" | path_xargs git-update-index --force-remove -- || error=1
102 rm "$TMPFILE" "$TMPDIRFILE"
104 [ "$error" ] && die "warning: not all items could have been removed"
105 exit 0