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.
|
||||
* When the user runs `git annex initremote foo type=external externaltype=$bar`,
|
||||
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
|
||||
things, a transcript of git-annex's communication with your program.
|
||||
* If you build a new special remote, please add it to the list
|
||||
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
|
||||
to run whatever commands you need. Or better, re-written in some better
|
||||
language of your choice. See [[design/external_special_remote_protocol]]
|
||||
for the details.
|
||||
language of your choice.
|
||||
|
||||
[[!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