add working external special remote for torrents
Not IMHO good enough quality to be more than an example, but it does work!
This commit is contained in:
parent
8a17bcb0be
commit
fabc3863d5
2 changed files with 197 additions and 2 deletions
|
@ -14,14 +14,18 @@ It's not hard!
|
||||||
* Install it in PATH.
|
* Install it in PATH.
|
||||||
* When the user runs `git annex initremote foo type=external externaltype=$bar`,
|
* When the user runs `git annex initremote foo type=external externaltype=$bar`,
|
||||||
it will use your program.
|
it will use your program.
|
||||||
|
* See [[design/external_special_remote_protocol]] for what the program
|
||||||
|
needs to do. There's an example at the end of this page.
|
||||||
* If things don't seem to work, pass `--debug` and you'll see, amoung other
|
* If things don't seem to work, pass `--debug` and you'll see, amoung other
|
||||||
things, a transcript of git-annex's communication with your program.
|
things, a transcript of git-annex's communication with your program.
|
||||||
* If you build a new special remote, please add it to the list
|
* If you build a new special remote, please add it to the list
|
||||||
of [[special_remotes]].
|
of [[special_remotes]].
|
||||||
|
|
||||||
|
Here's an example of using an external special remote to add torrent
|
||||||
|
support to git-annex: [[external/git-annex-remote-torrent]]
|
||||||
|
|
||||||
Here's a simple shell script example, which can easily be adapted
|
Here's a simple shell script example, which can easily be adapted
|
||||||
to run whatever commands you need. Or better, re-written in some better
|
to run whatever commands you need. Or better, re-written in some better
|
||||||
language of your choice. See [[design/external_special_remote_protocol]]
|
language of your choice.
|
||||||
for the details.
|
|
||||||
|
|
||||||
[[!inline pages="special_remotes/external/example.sh" feeds=no]]
|
[[!inline pages="special_remotes/external/example.sh" feeds=no]]
|
||||||
|
|
191
doc/special_remotes/external/git-annex-remote-torrent
vendored
Executable file
191
doc/special_remotes/external/git-annex-remote-torrent
vendored
Executable file
|
@ -0,0 +1,191 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# This is a demo git-annex external special remote program,
|
||||||
|
# which adds basic torrent download support to git-annex.
|
||||||
|
#
|
||||||
|
# Uses aria2c. Also needs the original bittorrent (or bittornado) for the
|
||||||
|
# btshowmetainfo command.
|
||||||
|
#
|
||||||
|
# Install in PATH as git-annex-remote-torrent
|
||||||
|
#
|
||||||
|
# Enable remote by running:
|
||||||
|
# git annex initremote torrent type=external encryption=none externaltype=torrent
|
||||||
|
# git annex untrust torrent
|
||||||
|
#
|
||||||
|
# Copyright 2014 Joey Hess; licenced under the GNU GPL version 3 or higher.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# This program speaks a line-based protocol on stdin and stdout.
|
||||||
|
# When running any commands, their stdout should be redirected to stderr
|
||||||
|
# (or /dev/null) to avoid messing up the protocol.
|
||||||
|
runcmd () {
|
||||||
|
"$@" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gets a VALUE response and stores it in $RET
|
||||||
|
getvalue () {
|
||||||
|
read resp
|
||||||
|
# Tricky POSIX shell code to split first word of the resp,
|
||||||
|
# preserving all other whitespace
|
||||||
|
case "${resp%% *}" in
|
||||||
|
VALUE)
|
||||||
|
RET="$(echo "$resp" | sed 's/^VALUE \?//')"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
RET=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get a list of all known torrent urls for a key,
|
||||||
|
# storing it in a temp file.
|
||||||
|
geturls () {
|
||||||
|
key="$1"
|
||||||
|
tmp="$2"
|
||||||
|
|
||||||
|
echo GETURLS "$key"
|
||||||
|
getvalue
|
||||||
|
while [ -n "$RET" ]; do
|
||||||
|
if istorrent "$RET"; then
|
||||||
|
echo "$RET" >> "$tmp"
|
||||||
|
fi
|
||||||
|
getvalue
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Does the url end in .torrent?
|
||||||
|
# Note that we use #N on the url to indicate which file
|
||||||
|
# from a multi-file torrent is wanted.
|
||||||
|
istorrent () {
|
||||||
|
echo "$1" | egrep -q "\.torrent(#.*)?$"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download a single file from a torrent.
|
||||||
|
#
|
||||||
|
# Note: Does not support resuming interrupted transfers.
|
||||||
|
# Note: Does not feed progress info back to git-annex, and since
|
||||||
|
# the destination file is only populated at the end, git-annex will fail
|
||||||
|
# to display a progress bar for this download.
|
||||||
|
downloadtorrent () {
|
||||||
|
torrent="$1"
|
||||||
|
n="$2"
|
||||||
|
dest="$3"
|
||||||
|
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
if ! runcmd aria2c --select-file="$n" "$torrent" -d "$tmpdir"; then
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# aria2c will create part of the directory structure
|
||||||
|
# contained in the torrent. It may download parts of other files
|
||||||
|
# in addition to the one we asked for. So, we need to find
|
||||||
|
# out the filename we want, and look for it.
|
||||||
|
wantdir="$(btshowmetainfo "$torrent" | grep "^directory name: " | sed "s/^directory name: //")"
|
||||||
|
wantfile="$(btshowmetainfo "$tmp" | grep '^ ' | sed 's/^ //' | head -n "$n" | tail -n 1 | sed 's/ ([0-9]*)$//')"
|
||||||
|
if [ -e "$tmpdir/$wantdir/$wantfile" ]; then
|
||||||
|
mv "$tmpdir/$wantdir/$wantfile" "$dest"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
else
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# This has to come first, to get the protocol started.
|
||||||
|
echo VERSION 1
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
set -- $line
|
||||||
|
case "$1" in
|
||||||
|
INITREMOTE)
|
||||||
|
echo INITREMOTE-SUCCESS
|
||||||
|
;;
|
||||||
|
PREPARE)
|
||||||
|
echo PREPARE-SUCCESS
|
||||||
|
;;
|
||||||
|
CLAIMURL)
|
||||||
|
url="$2"
|
||||||
|
if istorrent "$url"; then
|
||||||
|
echo CLAIMURL-SUCCESS
|
||||||
|
else
|
||||||
|
echo CLAIMURL-FAILURE
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
CHECKURL)
|
||||||
|
url="$2"
|
||||||
|
# List contents of torrent.
|
||||||
|
tmp=$(mktemp)
|
||||||
|
if ! runcmd curl -o "$tmp" "$url"; then
|
||||||
|
echo CHECKURL-FAILURE
|
||||||
|
else
|
||||||
|
oldIFS="$IFS"
|
||||||
|
IFS="
|
||||||
|
"
|
||||||
|
printf "CHECKURL-MULTI"
|
||||||
|
n=0
|
||||||
|
for l in $(btshowmetainfo "$tmp" | grep '^ ' | sed 's/^ //'); do
|
||||||
|
# Note that the file cannot contain spaces.
|
||||||
|
file="$(echo "$l" | sed 's/ ([0-9]*)$//' | sed 's/ /_/g')"
|
||||||
|
size="$(echo "$l" | sed 's/.* (\([0-9]*\))$/\1/')"
|
||||||
|
n=$(expr $n + 1)
|
||||||
|
printf " $url#$n $size $file"
|
||||||
|
done
|
||||||
|
printf "\n"
|
||||||
|
IFS="$oldIFS"
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
;;
|
||||||
|
TRANSFER)
|
||||||
|
key="$3"
|
||||||
|
file="$4"
|
||||||
|
case "$2" in
|
||||||
|
STORE)
|
||||||
|
runcmd echo "upload not supported"
|
||||||
|
echo TRANSFER-FAILURE STORE "$key"
|
||||||
|
;;
|
||||||
|
RETRIEVE)
|
||||||
|
urltmp=$(mktemp)
|
||||||
|
geturls "$key" "$urltmp"
|
||||||
|
url="$(head "$urltmp")" || true
|
||||||
|
rm -f "$urltmp"
|
||||||
|
if [ -z "$url" ]; then
|
||||||
|
echo TRANSFER-FAILURE RETRIEVE "$key" "no known torrent urls for this key"
|
||||||
|
else
|
||||||
|
tmp=$(mktemp)
|
||||||
|
if ! runcmd curl -o "$tmp" "$url"; then
|
||||||
|
echo TRANSFER-FAILURE RETRIEVE "$key" "failed downloading torrent file from $url"
|
||||||
|
else
|
||||||
|
filenum="$(echo "$url" | sed 's/.*#\(\d*\)/\1/')"
|
||||||
|
if downloadtorrent "$tmp" "$filenum" "$file"; then
|
||||||
|
echo TRANSFER-SUCCESS RETRIEVE "$key"
|
||||||
|
else
|
||||||
|
echo TRANSFER-FAILURE RETRIEVE "$key" "failed to download torrent contents from $url"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
CHECKPRESENT)
|
||||||
|
key="$2"
|
||||||
|
# Let's just assume that torrents are always present
|
||||||
|
# for simplicity.
|
||||||
|
echo CHECKPRESENT-SUCCESS "$key"
|
||||||
|
;;
|
||||||
|
REMOVE)
|
||||||
|
key="$2"
|
||||||
|
# Remove all torrent urls for the key.
|
||||||
|
tmp=$(mktemp)
|
||||||
|
geturls "$key" "$tmp"
|
||||||
|
for url in $(cat "$tmp"); do
|
||||||
|
echo SETURLMISSING "$key" "$url"
|
||||||
|
done
|
||||||
|
rm -f "$tmp"
|
||||||
|
echo REMOVE-SUCCESS "$key"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo UNSUPPORTED-REQUEST
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
Loading…
Reference in a new issue