A simplistic attempt to provide a FUSE1 read-write interface to a Git repository. The possibilities are endless ;)
This is Free Software. You can redistribute it and/or modify it under the terms of either The GNU General Public License2, as published by the Free Software Foundation3, Version 1 or any later version4, or The Artistic License5.
- A non-faint heart
- fuse modules installed and configured for the current user
- perl-fuse6 compiled and installed
Launching git-fuse
inside a checked-out Git repository, and giving it an
empty directory name as a parameter will make available the heads and tags of
that Git repository as subdirectories of the mountpoint's heads
or tags
directory, and the tree files are reachable from those heads and tags as files
in the filesystem.
Tags directories contain also special files showing the tag's message and signature verification.
The tags' directories are made available with permissions r-xr-xr-x
and the
files with permissions r--r--r--
, regardless of the permissions set in the
Git repository. Files and directories on heads are instead made available with
the permissions gathered from the Git information. UID and GID are the ones of
the user which fusermounts the repository.
You can launch a test doing make start-fuse
. Navigate the filesystem under
mountpoint/ at your leisure, then issue make stop-fuse
when bored.
Untar the test-repos.tar and navigate it using Git or gitk. You'll see it contains silly commits and files and branches.
$ git show-branch
! [all_merged] Merge branch 'pl_stuff' into all_merged
! [c_branch] hello world and compiled
* [master] Added stuff
! [pl_stuff] And a Perl file
----
- [all_merged] Merge branch 'pl_stuff' into all_merged
+ + [pl_stuff] And a Perl file
+ + [pl_stuff^] Some utf8 text
++ [c_branch] hello world and compiled
++*+ [master] Added stuff
By launching "make" (or untarring and launching git-fuse separately)
you will find the following files under the mountpoint test/
:
$ find mountpoint/
mountpoint/
mountpoint/tags
mountpoint/tags/exe_changed
mountpoint/tags/exe_changed/__TAG__SIGNATURE__
mountpoint/tags/exe_changed/__TAG__MESSAGE__
mountpoint/tags/exe_changed/exe
...
mountpoint/tags/c_branch_tag_1
mountpoint/tags/c_branch_tag_1/__TAG__SIGNATURE__
mountpoint/tags/c_branch_tag_1/__TAG__MESSAGE__
mountpoint/tags/c_branch_tag_1/c
mountpoint/tags/c_branch_tag_1/c/main.c
mountpoint/tags/c_branch_tag_1/b
...
mountpoint/heads
mountpoint/heads/pl_stuff
mountpoint/heads/pl_stuff/pl
mountpoint/heads/pl_stuff/pl/polish.txt
mountpoint/heads/pl_stuff/pl/hello.pl
...
mountpoint/heads/master
mountpoint/heads/master/b
mountpoint/heads/master/b/c
mountpoint/heads/master/b/c/d
mountpoint/heads/master/b/c/d/e.txt
...
mountpoint/heads/all_merged
mountpoint/heads/all_merged/pl
mountpoint/heads/all_merged/pl/polish.txt
mountpoint/heads/all_merged/pl/hello.pl
mountpoint/heads/all_merged/c
mountpoint/heads/all_merged/c/main.c
...
mountpoint/heads/all_merged/a.out
Your Git repository is made available as a filesystem. What you do with that is entirely up to you. Here's some suggestions: make available all your branches of a website as separate hostnames; visually navigate the (branches' or tags') history of a repository via your favourite file manager. Since the data is not cached, you can effectively continue working on your checked-out repository, and the directory structure will morph along with your changes.
Entity | Thing | Read | Write | Create | Delete |
-------+-------+------+-------+--------+--------+
Files | HEADs | Y | Y (a) | Y (b) | Y |
Dirs | HEADs | Y | n/a | Y (c) | ? |
-------+-------+------+-------+--------+--------+
Files | TAGs | Y | N (d) | N (d) | N (d) |
Dirs | TAGs | Y | N (d) | N (d) | N (d) |
-------+-------+------+-------+--------+--------+
caveats:
a) one file is committed at a time, on the tip of the HEAD
b) a new file is committed empty, then a) happens
c) A `.keep` file is created inside the new directory
and committed.
d) Trees reachable from Tags are read-only.
Special files or directories are also littered around the filesystem (sorry!). These are:
In each tags' first directory ( mountpoint/tag/tagname/ ) there are two special files:
\_\_TAG\_\_MESSAGE\_\_ shows the message associated with the tag
\_\_TAG\_\_SIGNATURE\_\_ shows the GPG signature of the tag
The code uses qx{} for shelling out to Git for getting information about trees and blobs. Hopefully this should be moved to using git-pureperl7 or a better (faster?) interface. There is a lot of code repetition when splitting the paths for the heads and tags.
I am quite amazed it does cd, ls, cat and touch, to be perfectly honest.