This set of bash scripts allows one to clone/fetch/pull git repositories using gnunet, specifically the GNS and cadet.
In the interest of demonstrating that it works, this repo is available at
- `gnunet://git-over-gnunet.serv.000G0000V4BD1K10PRPGDKR916362AFZ12DBGA378EFRWPB0M54WHGX3YC`.
+ `gnunet://git.serv.000G0000V4BD1K10PRPGDKR916362AFZ12DBGA378EFRWPB0M54WHGX3YC/git-over-gnunet`.
Try cloning it ! (And do tell me if it fails, or if it works.)
Usage:
Client:
You must add the repo folder to the GIT_EXEC_PATH (for example by prepending
- `GIT_EXEC_PATH=$GIT_EXEC_PATH:<path-to-repo>` before every git command that uses remotes).
- The URL to give to git is gnunet://<GNS name of the repo>.
+ `GIT_EXEC_PATH=$GIT_EXEC_PATH:<path-to-git-over-gnunet-repo>` before every git command that uses remotes).
+ The URL to give to git is gnunet://<location of the repo>/<name of the repo>.
Server:
- To run the server on a repo, simply copy the two .sh files to its root, and run
- `./run-daemons.sh <ego> <repo-name>`.
- - This will open the repo for pulling on the GNS name `<repo-name>.<ego>`.
+ `./run-daemons.sh <ego> <gns-name> <repo-name>`.
+ - This will open the repo for pulling on the url `gnunet://<gns-name>.<ego>/<repo-name>`.
Features:
- Clone repo !
- Pulling from anyone using a commit hash ?
- DHT to figure out who has what commits ?
- Question of trust for pulling from peers ?
+ - Multiple repos.
How it works:
Client:
- Uses a git remote helper to give git the ability to interpet the gnunet:// scheme.
- - Gets the TXT record associated with the GNS name given after the gnunet://.
- - This TXT record is of the form <peer-id>:<port>.
- - To run a specific git command and get its inputs and outputs, connect via cadet
- to the peer id <peer-id>, via the port <port>-<command>.
+ - Gets the TXT record associated with the GNS name given after the gnunet://<gns-name>/<repo-name>.
+ - This TXT record is a <peer-id>.
+ - To run a specific git command on repo <repo> and get its inputs and outputs, connect via cadet
+ to the peer id <peer-id>, via the port git.<repo-name>-<command>.
- This is used by the remote helper to run git-upload-pack remotely.
Server:
- The server just loops on a cadet server with inputs and outputs connected to the specified git-command.
#!/usr/bin/env bash
mktempfifo() {
- name="$(mktemp -u)"
- mkfifo "$name" || mktempfifo
+ fifo_name="$(mktemp -u)"
+ mkfifo "$fifo_name" || mktempfifo
}
if test -z $1 || test -z $2 || ! test -z $3; then
- echo >&2 "Usage: $0 <service> <passphrase>"
+ echo >&2 "Usage: $0 <service> <name>"
exit 1
fi
service="$1"
-passphrase="$2"
+name="$2"
-echo >&2 "Running $service on port $passphrase-git-$service."
+echo >&2 "Running $service on port \`git.$name.git-$service'."
mktempfifo
-while < "$name" gnunet-cadet -o "$passphrase-git-$service" | git "$service" . | (cat; sleep 0.1) | cat > "$name"; test 130 != "$?"; do
- rm "$name"
+while < "$fifo_name" gnunet-cadet -o "git.$name.git-$service" | git "$service" . | (cat; sleep 0.1) | cat > "$fifo_name"; test 130 != "$?"; do
+ rm "$fifo_name"
mktempfifo
done
-rm $name
+rm $fifo_name
-echo >&2 "Terminating $service on port $passphrase-$service."
+echo >&2 "Terminating $service on port \`git.$name.git-$service'."
#!/usr/bin/env bash
if [[ "$2" = gnunet://* ]]; then
- gns=${2:9}
+ addr=${2:9}
else
- gns=$2
+ addr=$2
fi
+gns="$(echo "$addr" | cut -d/ -f1)"
+repo="$(echo "$addr" | cut -d/ -f2)"
+if test -z "$gns" || test -z "$repo" || ! test -z "$(echo "$addr" | cut -d/ -f3-)"; then
+ echo >&2 "Invalid address: \`$2'."
+ echo >&2 "Format: \`gnunet://gns-name/repo-name'."
+ echo >&2 " or \`gnunet::gns-name/repo-name'."
+ exit 1
+fi
+
while read -r cmd arg; do
case "$cmd" in
echo ''
echo >&2 "Looking up $gns."
-server="$(gnunet-gns -u "$gns" -t TXT -r)"
-if test -z "$server"; then
+peer="$(gnunet-gns -u "$gns" -t TXT -r)"
+if test -z "$peer"; then
echo >&2 "Address lookup failed: \`$gns'."
exit 1
fi
-peer="$(echo "$server" | cut -d: -f1)"
-port="$(echo "$server" | cut -d: -f2)"
-echo >&2 "Attempting to connect to peer $peer, on port $port-$arg."
-(stdbuf -i0 -o0 -e0 cat; sleep 0.01) | gnunet-cadet "$peer" "$port-$arg"
+port="git.$repo.$arg"
+echo >&2 "Attempting to connect to peer $peer, on port \`$port'."
+(stdbuf -i0 -o0 -e0 cat; sleep 0.01) | gnunet-cadet "$peer" "$port"
#!/usr/bin/env bash
-if test -z $1 || test -z $2 || ! test -z $3; then
- echo >&2 "Usage: $0 <ego> <repo-name>"
+if test -z $1 || test -z $2 || test -z $3 || ! test -z $4; then
+ echo >&2 "Usage: $0 <ego> <name> <repo-name>"
exit 1
fi
ego="$1"
name="$2"
+repo_name="$3"
-echo >&2 "Running pullable repo $name in ego $ego."
-gnunet-namestore -a -t TXT -e 1d -n "$name" -V "$(gnunet-core -i | sed 's/.*: //'):$name" -z "$ego" -p
+echo >&2 "Running pullable repo $repo_name as \`$name.$ego'."
+gnunet-namestore -a -t TXT -e 1d -n "$name" -V "$(gnunet-core -i | sed 's/.*: //')" -z "$ego" -p
-./daemon.sh upload-pack "$name"
+./daemon.sh upload-pack "$repo_name"
gnunet-namestore -d -n "$name" -z "$ego"
-echo >&2 "Terminating pullable repo $name in ego $ego."
+echo >&2 "Terminating pullable repo $repo_name in ego $ego."