Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit a8f45685384a4b1648a42489d47162e312102dfd @duairc committed Mar 17, 2010
Showing with 120 additions and 0 deletions.
  1. +8 −0 README
  2. +29 −0 bin/git-mount
  3. +83 −0 lib/gitfs.rb
8 README
@@ -0,0 +1,8 @@
+git mount
+=========
+
+This is a really simple script that connects Ruby's [Grit](http://github.com/mojombo/grit) and [FuseFS](http://fusefs.sourceforge.net/) libraries together. You can do `git mount /tmp/blah` in your git repository, and then in `/tmp/blah` you will have a (read-only) filesystem where view the different branches and tags of your repository simultaneously.
+
+It is horrendously slow for even moderately sizes repositories though... I suspect the bottleneck is Grit, but on a moral level the idea of `ls` having to interpret Ruby code offends me. I fully intend to rewrite this in C, but in case that never happens, here's what I have so far.
+
+By the way, you can unmount the filesystem with `fusermount -u /tmp/blah`.
29 bin/git-mount
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby1.9.1
+require 'fusefs'
+require 'gitfs'
+require 'optparse'
+
+options = {git: '.'}
+parser = OptionParser.new do |opts|
+ opts.banner = "Usage: git mount [OPTION...] MOUNTPOINT"
+ opts.separator "\nOptions:"
+ opts.on("-g", "--git REPO", "Mount the git repository at REPO (default: .).") do |repo|
+ options[:git] = repo
+ end
+end
+parser.parse!
+options[:mountpoint] = parser.instance_variable_get(:@default_argv)[0]
+
+
+pid = fork do
+ trap('HUP', 'IGNORE')
+ trap('SIGTERM') do
+ FuseFS.exit
+ end
+
+ filesystem = GitFS.new(options[:git])
+ FuseFS.set_root(filesystem)
+ FuseFS.mount_under(options[:mountpoint])
+ FuseFS.run
+end
+Process.detach(pid)
83 lib/gitfs.rb
@@ -0,0 +1,83 @@
+require 'grit'
+require 'fusefs'
+
+class Grit::Blob
+ def find(path)
+ path == '' or path == nil or nil
+ end
+end
+
+class Grit::Tree
+ def find(path)
+ case path
+ when /^\/?$/, nil
+ self
+ when /^\/?([^\/]+)$/
+ contents.find{|t| t.basename == $1}
+ when /^\/?([^\/]+)\/(.*)$/
+ contents.find{|t| t.basename == $1}.find($2)
+ else
+ p path
+ end
+ end
+
+ def ls(path)
+ find(path).contents.map(&:basename)
+ end
+end
+
+class GitFS < FuseFS::FuseDir
+ def initialize(repo_path)
+ @repo = Grit::Repo.new(repo_path)
+ end
+
+ def contents(path)
+ case path
+ when '/branch'
+ @repo.branches.map(&:name)
+ when '/tag'
+ @repo.tags.map(&:name)
+ when '/'
+ ['branch', 'tag']
+ when /^\/(branch|tag)\/([^\/]+)(\/.*)?$/
+ @repo.tree($2).ls($3)
+ else
+ []
+ end
+ end
+
+ def directory?(path)
+ case path
+ when '/', '/branch', '/tag'
+ true
+ when /^\/branch\/([^\/]+)$/
+ @repo.branches.find{|t| t.name == $1}
+ when /^\/tag\/([^\/]+)$/
+ @repo.tags.find{|t| t.name == $1}
+ when /^\/(branch|tag)\/([^\/]+)\/(.*)/
+ Grit::Tree === @repo.tree($2).find($3)
+ else
+ false
+ end
+ end
+
+ def file?(path)
+ case path
+ when /^\/(branch|tag)\/([^\/]+)\/(.*)/
+ p (r = @repo.tree($2)).contents.map(&:basename)
+ p $3
+ Grit::Blob === @repo.tree($2).find($3)
+ else
+ false
+ end
+ end
+
+ def size(path)
+ read_file(path).size
+ end
+
+ def read_file(path)
+ path =~ /^\/(branch|tag)\/([^\/]+)\/(.*)/
+ @repo.tree($2).find($3).data
+ end
+end

0 comments on commit a8f4568

Please sign in to comment.