mktar: Use `wc` instead of `du` in summary message
[sunny256-utils.git] / ga
blob3dcef2377e6c9354ab7bb5e70064a5e07a8762ed
1 #!/usr/bin/env bash
3 #=======================================================================
4 # ga
5 # File ID: e89047ce-29d1-11e2-bb6f-00c0a8deee11
7 # Customised frontend to git-annex
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #=======================================================================
13 progname=ga
14 VERSION=0.17.0
16 if test "$1" = "--version"; then
17 echo $progname $VERSION
18 exit 0
21 if test "$1" = "-h" -o "$1" = "--help"; then
22 cat <<END
24 Customised frontend to git-annex.
26 Usage: $progname [options] git-annex_commands_and_options
28 The following commands (first non-option on the command line) are
29 customised:
31 chk
32 Verify the file contents with ga-key(1) against the key stored in
33 the symlink. Only supports SHA256 for now.
34 copnum
35 Like "git annex numcopies", but always return a number. If numcopies
36 is not defined, return 1.
37 fsck
38 Filter the output through ga-fsck-size, calculates how much space is
39 needed to get enough file copies.
40 init
41 If annex.uuid isn't already defined, initialise annex.uuid with an
42 UUID v1 (time-based UUID) instead of v4 (random-based). This is done
43 before executing an ordinary "git annex init". If a description is
44 provided on the command line after the "init" command, use that, or
45 set the description to the value of the ga.description Git config
46 variable if it exists. Otherwise use the output from the "ga-pwd"
47 command. The script will abort if annex.uuid is already defined.
48 Also, if any other command than init is executed and annex.uuid
49 doesn't exist, the script aborts. This is to make sure no git-annex
50 setup is done in non-annex repositories.
51 max-bytes SIZE COMMAND
52 Execute git-annex with a modified annex.diskreserve locally so the
53 local free annex space seems to be SIZE. This can be used to for
54 example move maximum SIZE bytes from another repo to the local one:
55 ga max-bytes 1000000 move --from exthd --not --in here
56 will move at most 1 megabyte from the exthd remote. Note that
57 because it uses the annex.diskreserve Git config variable as a
58 workaround, it will be affected if the actual disk space changes. It
59 works best when there's no other activity on the local disk going
60 on.
62 Shortcut for "metadata".
63 snp
64 Shortcut for "ga sync --no-push".
65 sync
66 If the Git config variable annex.autocommit is not "false", execute
67 "git wait-until-clean -u" before syncing, i.e., wait until the
68 repository is clean before continuing. This is to avoid any
69 accidental commits.
70 Run "git-annex merge" before sync to get local modifications in
71 place in case "git-annex sync" doesn't do it properly.
72 Also, update all local synced/* branches by running "git pa -s". If
73 you have a Git-aware command line prompt that shows if the current
74 branch is behind or ahead upstream, it will show when a sync or
75 merge is needed.
77 Shortcut for "update-desc".
78 unused
79 Filter the output through ga-sumsize, display total number of bytes
80 in unused files.
81 update-desc
82 Update the git-annex description, use the generic output from
83 ga-pwd. For example, the output for the current directory is
84 "`ga-pwd`".
85 If the git config key ga.description is defined, that value is used
86 instead. This can be used if some repos have to be called something
87 else than what the ga-pwd value says.
89 After all this, it disables "git annex pre-commit ." in
90 .git/hooks/pre-commit if it's not already disabled. This is to avoid an
91 automatic "git annex fix" that automatically fixes broken symlinks
92 before commit. It makes it hard to track file renames, as it breaks "git
93 log --follow" and friends.
95 Options:
97 -h, --help
98 Show this help.
99 --version
100 Print version information.
103 exit 0
106 disk_free() {
107 df -B 1 -P . | tail -1 | tr -s ' ' | cut -f 4 -d ' ' | tr -d '\n'
110 if test "$1" = "init"; then
111 if test -z "$(git config --get annex.uuid)"; then
112 git config annex.uuid $(suuid -wa -t ga_init)
113 shift
114 if test -n "$1"; then
115 git-annex init "$@"
116 elif test -n "$(git config --get ga.description)"; then
117 git-annex init "$(git config --get ga.description)"
118 else
119 git-annex init "$(ga-pwd)"
121 exit
122 else
123 echo $progname: Repository is already initialised for git-annex >&2
124 exit 1
126 else
127 if test -z "$(git config --get annex.uuid)"; then
128 echo $progname: annex.uuid is not defined, aborting >&2
129 exit 1
133 # Check that "git annex pre-commit ." is commented out in
134 # .git/hooks/pre-commit, I don't want to let "git commit" run "git annex
135 # fix" automatically when I've moved files around. I want to be able to
136 # track moves, and it breaks "git log --follow". If it's not disabled,
137 # do it automatically.
138 precommit="$(git rev-parse --show-toplevel)/.git/hooks/pre-commit"
139 if test -f "$precommit"; then
140 grep -q '^git.*annex.*pre-commit' "$precommit" && {
141 perl -p -i -e 's/^(git.annex.+pre-commit)/# $1/' "$precommit"
142 echo $progname: $precommit: Have disabled git annex pre-commit: >&2
143 cat "$precommit" >&2
147 exitval=0
148 sha256key_regexp='/SHA256-s[0-9]+--[0-9a-f]{64}$'
150 if test "$1" = "chk"; then
151 shift
152 for f in "$@"; do
153 if test -L "$f" -a -d "$f"; then
154 echo $progname: $f: Is a symlink to a directory >&2
155 continue
157 if test -d "$f"; then
158 echo $progname: $f: Is a directory >&2
159 continue
161 if test -L "$f" -a ! -e "$f"; then
162 if readlink "$f" | grep -Eq $sha256key_regexp; then
163 echo $progname: $f: File not present here >&2
164 else
165 echo $progname: $f: Broken symlink >&2
167 continue
169 if test ! -e "$f"; then
170 echo $progname: $f: File not found >&2
171 exitval=1
172 continue
174 if test ! -L "$f"; then
175 echo $progname: $f: Not a symbolic link >&2
176 continue
178 if ! readlink "$f" | grep -Eq $sha256key_regexp; then
179 echo $progname: $f: SHA256 key not found in symlink >&2
180 continue
182 if test ! -r "$f"; then
183 echo $progname: $f: File is not readable by you >&2
184 exitval=1
185 continue
187 key=$(ga-key "$f")
188 echo -n "$f "
189 readlink "$f" | grep -q $key && echo ok || { echo fail; exitval=1; }
190 done
191 exit $exitval
192 elif test "$1" = "copnum"; then
193 if test -n "$(ga numcopies | grep "is not set")"; then
194 echo 1
195 else
196 git annex numcopies
198 elif test "$1" = "fsck"; then
199 shift
200 git-annex fsck "$@" 2>&1 | ga-fsck-size
201 elif test "$1" = "max-bytes"; then
202 maxbytes=$2
203 if test -z "$maxbytes"; then
204 echo $progname: max-bytes needs an integer argument >&2
205 exit 1
207 shift 2
208 git-annex "$@" -c annex.diskreserve=$(echo $(disk_free)-$maxbytes | bc)
209 elif test "$1" = "md"; then
210 shift
211 git-annex metadata "$@"
212 elif test "$1" = "snp"; then
213 shift
214 ga sync --no-push "$@"
215 elif test "$1" = "sync"; then
216 if test "$(git config --get annex.autocommit)" != "false"; then
217 git wait-until-clean -u
219 git-annex merge
220 git-annex "$@"
221 git pa -s
222 elif test "$1" = "unused"; then
223 shift
224 git-annex unused "$@" | ga-sumsize
225 elif test "$1" = "update-desc" -o "$1" = "ud"; then
226 toplevel="$(git rev-parse --show-toplevel)"
227 cd "$toplevel" || {
228 echo $progname update-desc: $toplevel: Cannot change to directory >&2
229 exit 1
231 description="$(git config --get ga.description)"
232 if test -n "$description"; then
233 here="$description"
234 else
235 here="$(ga-pwd)"
237 repouuid="$(git config --get annex.uuid)"
238 if test -z "$repouuid"; then
239 echo $progname: annex.uuid is empty, seems as it is not an annex >&2
240 exit 1
242 info_line="$(ga info --fast | grep $repouuid)"
243 found_it=0
244 # FIXME: The regexp is relaxed here because some suspicious
245 # behaviour from git-annex, it places remotes there. They're also in
246 # the JSON output, so it looks like a bug. — Sønnyen, 2016-04-29
247 echo "$info_line" | grep -q " -- $here .*\\[here\\]" && found_it=1
248 if test "$found_it" = "1"; then
249 echo $progname: Description looks ok, not changing it >&2
250 exit 0
251 else
252 ga sync
253 sess -- ga describe here "$here"
254 ga sync
255 echo
256 echo $progname update-desc: Before: $info_line >&2
257 echo $progname update-desc: After : $(
258 ga info --fast | grep $repouuid
259 ) >&2
260 echo
262 else
263 git-annex "$@"