diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..817f62a --- /dev/null +++ b/Gemfile @@ -0,0 +1,2 @@ +source 'http://rubygems.org' +gemspec diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..a622293 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,51 @@ +PATH + remote: . + specs: + git-media (0.1.4) + right_aws + ruby-atmos-pure + s3 + trollop + +GEM + remote: http://rubygems.org/ + specs: + diff-lcs (1.1.3) + git (1.2.5) + jeweler (1.8.4) + bundler (~> 1.0) + git (>= 1.2.5) + rake + rdoc + json (1.7.5) + log4r (1.1.10) + proxies (0.2.1) + rake (0.9.2.2) + rdoc (3.12) + json (~> 1.4) + right_aws (3.0.4) + right_http_connection (>= 1.2.5) + right_http_connection (1.3.0) + rspec (2.11.0) + rspec-core (~> 2.11.0) + rspec-expectations (~> 2.11.0) + rspec-mocks (~> 2.11.0) + rspec-core (2.11.1) + rspec-expectations (2.11.3) + diff-lcs (~> 1.1.3) + rspec-mocks (2.11.3) + ruby-atmos-pure (1.0.5) + log4r (>= 1.1.9) + ruby-hmac (>= 0.4.0) + ruby-hmac (0.4.0) + s3 (0.3.11) + proxies (~> 0.2.0) + trollop (2.0) + +PLATFORMS + ruby + +DEPENDENCIES + git-media! + jeweler + rspec diff --git a/README.rdoc b/README.rdoc index 94d9ae2..374ef1e 100644 --- a/README.rdoc +++ b/README.rdoc @@ -7,18 +7,18 @@ without storing the media in Git itself. Setup the attributes filter settings. - (once after install) - $ git config filter.media.clean "git-media filter-clean" - $ git config filter.media.smudge "git-media filter-smudge" + (once after install) + $ git config filter.media.clean "git-media filter-clean" + $ git config filter.media.smudge "git-media filter-smudge" Setup the .gitattributes file to map extensions to the filter. - (in repo - once) - $ echo "*.mov filter=media -crlf" > .gitattributes + (in repo - once) + $ echo "*.mov filter=media -crlf" > .gitattributes -Staging files with those extensions will automatically copy them to the +Staging files with those extensions will automatically copy them to the media buffer area (.git/media) until you run 'git media sync' wherein they -are uploaded. Checkouts that reference media you don't have yet will try to +are uploaded. Checkouts that reference media you don't have yet will try to be automatically downloaded, otherwise they are downloaded when you sync. Next you need to configure git to tell it where you want to store the large files. @@ -28,72 +28,78 @@ There are four options: 2. Storing locally in a filesystem path 3. Storing remotely via SCP (should work with any SSH server) 4. Storing remotely in atmos +5. Storing remotely in Google Drive Here are the relevant sections that should go either in ~/.gitconfig (for global settings) or in clone/.git/config (for per-repo settings). - [git-media] - transport = - - # settings for scp transport - scpuser= - scphost= - scppath= + [git-media] + transport = - # settings for local transport - path= + # settings for scp transport + scpuser= + scphost= + scppath= - # settings for s3 transport - s3bucket= - s3key= - s3secret= + # settings for local transport + path= - # settings for atmos transport - endpoint= - uid= - secret= - tag= + # settings for s3 transport + s3bucket= + s3key= + s3secret= + # settings for atmos transport + endpoint= + uid= + secret= + tag= + + # settings for drive transport + email= + asp= + collection= == Usage - (in repo - repeatedly) - $ (hack, stage, commit) - $ git media sync + (in repo - repeatedly) + $ (hack, stage, commit) + $ git media sync -You can also check the status of your media files via +You can also check the status of your media files via - $ git media status + $ git media status Which will show you files that are waiting to be uploaded and how much data that is. If you want to upload & delete the local cache of media files, run: - $ git media clear + $ git media clear == Config Settings - $ git config --global media.auto-download false + $ git config --global media.auto-download false -== Installing +== Installing $ sudo gem install trollop $ sudo gem install s3 + $ sudo gem install google_drive $ sudo gem install ruby-atmos-pure $ sudo gem install right_aws $ gem build git-media.gemspec $ sudo gem install git-media-0.1.1.gem == Notes for Windows -It is important to switch off git smart newline character support for media files. +It is important to switch off git smart newline character support for media files. Use "-crlf" switch in .gitattributes (for example "*.mov filter=media -crlf") or config option "core.autocrlf = false". If installing on windows, you might run into a problem verifying certificates for S3 or something. If that happens, modify - C:\Ruby191\lib\ruby\gems\1.9.1\gems\right_http_connection-1.2.4\lib\right_http_connection.rb + C:\Ruby191\lib\ruby\gems\1.9.1\gems\right_http_connection-1.2.4\lib\right_http_connection.rb And add at line 310, right before "@http.start": - @http.verify_mode = OpenSSL::SSL::VERIFY_NONE + @http.verify_mode = OpenSSL::SSL::VERIFY_NONE == Copyright diff --git a/Rakefile b/Rakefile index a410e28..1f56890 100644 --- a/Rakefile +++ b/Rakefile @@ -16,22 +16,15 @@ rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" end -require 'spec/rake/spectask' -Spec::Rake::SpecTask.new(:spec) do |spec| - spec.libs << 'lib' << 'spec' - spec.spec_files = FileList['spec/**/*_spec.rb'] +require 'rspec/core/rake_task' +RSpec::Core::RakeTask.new(:spec) do |spec| + spec.pattern = 'spec/**/*_spec.rb' + spec.rspec_opts = ['--backtrace'] end -Spec::Rake::SpecTask.new(:rcov) do |spec| - spec.libs << 'lib' << 'spec' - spec.pattern = 'spec/**/*_spec.rb' - spec.rcov = true -end - - task :default => :spec -require 'rake/rdoctask' +require 'rdoc/task' Rake::RDocTask.new do |rdoc| if File.exist?('VERSION.yml') config = YAML.load(File.read('VERSION.yml')) diff --git a/VERSION b/VERSION index d917d3e..845639e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.2 +0.1.4 diff --git a/git-media.gemspec b/git-media.gemspec index 74a25c1..48dae20 100644 --- a/git-media.gemspec +++ b/git-media.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = %q{git-media} - s.version = "0.1.2" + s.version = "0.1.4" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Scott Chacon"] @@ -33,6 +33,7 @@ Gem::Specification.new do |s| "lib/git-media/transport/s3.rb", "lib/git-media/transport/atmos_client.rb", "lib/git-media/transport/scp.rb", + "lib/git-media/transport/drive.rb", "lib/git-media/transport.rb", "lib/git-media.rb" ] @@ -43,6 +44,13 @@ Gem::Specification.new do |s| s.rubygems_version = %q{1.3.1} s.summary = %q{"This is a summary! Stop yer whining"} + s.add_dependency 'trollop' + s.add_dependency 's3' + s.add_dependency 'ruby-atmos-pure' + s.add_dependency 'right_aws' + s.add_development_dependency 'jeweler' + s.add_development_dependency 'rspec' + if s.respond_to? :specification_version then current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION s.specification_version = 2 diff --git a/lib/git-media.rb b/lib/git-media.rb index 3c32810..49c2131 100644 --- a/lib/git-media.rb +++ b/lib/git-media.rb @@ -15,9 +15,9 @@ def self.get_media_buffer def self.media_path(sha) buf = self.get_media_buffer - File.join(buf, sha) + File.join(buf, sha) end - + # TODO: select the proper transports based on settings def self.get_push_transport self.get_transport @@ -34,20 +34,20 @@ def self.get_transport path = `git config git-media.scppath`.chomp port = `git config git-media.scpport`.chomp if user === "" - raise "git-media.scpuser not set for scp transport" + raise "git-media.scpuser not set for scp transport" end if host === "" - raise "git-media.scphost not set for scp transport" + raise "git-media.scphost not set for scp transport" end if path === "" - raise "git-media.scppath not set for scp transport" + raise "git-media.scppath not set for scp transport" end GitMedia::Transport::Scp.new(user, host, path, port) when "local" path = `git config git-media.localpath`.chomp if path === "" - raise "git-media.localpath not set for local transport" + raise "git-media.localpath not set for local transport" end GitMedia::Transport::Local.new(path) when "s3" @@ -55,13 +55,13 @@ def self.get_transport key = `git config git-media.s3key`.chomp secret = `git config git-media.s3secret`.chomp if bucket === "" - raise "git-media.s3bucket not set for s3 transport" + raise "git-media.s3bucket not set for s3 transport" end if key === "" - raise "git-media.s3key not set for s3 transport" + raise "git-media.s3key not set for s3 transport" end if secret === "" - raise "git-media.s3secret not set for s3 transport" + raise "git-media.s3secret not set for s3 transport" end GitMedia::Transport::S3.new(bucket, key, secret) when "atmos" @@ -83,6 +83,21 @@ def self.get_transport raise "git-media.secret not set for atmos transport" end GitMedia::Transport::AtmosClient.new(endpoint, uid, secret, tag) + when "drive" + require 'git-media/transport/drive' + email = `git config git-media.email`.chomp + asp = `git config git-media.asp`.chomp + collection = `git config git-media.collection`.chomp + if email == "" + raise "git-media.email not set for drive transport" + end + if asp == "" + raise "git-media.asp (application specific password) not set for drive transport" + end + if collection == "" + raise "git-media.collection not set for drive transport" + end + GitMedia::Transport::Drive.new(email, asp, collection) else raise "Invalid transport #{transport}" end @@ -94,7 +109,7 @@ def self.get_pull_transport module Application def self.run! - + cmd = ARGV.shift # get the subcommand cmd_opts = case cmd when "filter-clean" # parse delete options @@ -125,7 +140,7 @@ def self.run! EOF end - + end end end diff --git a/lib/git-media/filter-smudge.rb b/lib/git-media/filter-smudge.rb index 0a8c6d1..eca3661 100644 --- a/lib/git-media/filter-smudge.rb +++ b/lib/git-media/filter-smudge.rb @@ -6,7 +6,7 @@ def self.run! can_download = false # TODO: read this from config and implement # read checksum size - sha = STDIN.readline(64).strip # read no more than 64 bytes + sha = STDIN.readpartial(64).lines.first.chomp # read no more than 64 bytes if STDIN.eof? && sha.length == 40 && sha.match(/^[0-9a-fA-F]+$/) != nil # this is a media file media_file = File.join(media_buffer, sha.chomp) @@ -35,4 +35,4 @@ def self.run! end end -end \ No newline at end of file +end diff --git a/lib/git-media/transport/drive.rb b/lib/git-media/transport/drive.rb new file mode 100644 index 0000000..bee8a58 --- /dev/null +++ b/lib/git-media/transport/drive.rb @@ -0,0 +1,45 @@ +require 'git-media/transport' +require 'google_drive' + +# git-media.transport drive +# git-media.email youname@gmail.com +# git-media.asp application specific password +# git-media.collection collectionName (should be shared with all users) + +module GitMedia + module Transport + class Drive < Base + + def initialize(email, asp, collection) + @drive = GoogleDrive.login(email, asp) + @collection = @drive.collection_by_title(collection) + end + + def read? + true + end + + def get_file(sha, to_file) + file = @collection.files("title" => sha, "title-exact" => true).first + file.download_to_file(to_file) + end + + def write? + true + end + + def put_file(sha, from_file) + f = @drive.upload_from_file(from_file, sha, :convert => false) + @collection.add(f) + end + + def get_unpushed(files) + keys = @collection.files.map { |f| f.title } + files.select do |f| + !keys.include?(f) + end + end + + end + end +end diff --git a/spec/media_spec.rb b/spec/media_spec.rb index 0a6a106..38c7235 100644 --- a/spec/media_spec.rb +++ b/spec/media_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') +require 'spec_helper' # I realize this is horrible, horrible rspec but I want to run the actual # git commands and it takes forever to setup the test env each time, so @@ -12,7 +12,7 @@ git("commit -m 'testing'") # check that we saved the sha and not the data - size = git("cat-file -s master:testing1.mov") + size = git("cat-file -s master:testing1.x22") size.should eql('41') # check that the data is in our buffer area @@ -22,15 +22,15 @@ end # check that removing the file and checking out returns the data - File.unlink('testing1.mov') - git('checkout testing1.mov') - File.size('testing1.mov').should eql(7) + File.unlink('testing1.x22') + git('checkout testing1.x22') + File.size('testing1.x22').should eql(7) # check that removing the file and checking out sans data returns the sha - File.unlink('testing1.mov') + File.unlink('testing1.x22') File.unlink('.git/media/objects/20eabe5d64b0e216796e834f52d61fd0b70332fc') - git('checkout testing1.mov') - File.size('testing1.mov').should eql(41) + git('checkout testing1.x22') + File.size('testing1.x22').should eql(41) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 73c1504..dcb676a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,4 @@ require 'rubygems' -require 'spec' require 'tempfile' require 'pp' @@ -7,7 +6,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'git-media' -Spec::Runner.configure do |config| +RSpec.configure do |config| end def in_temp_git @@ -24,12 +23,12 @@ def in_temp_git def in_temp_git_w_media bin = File.join(File.dirname(__FILE__), '..', 'bin', 'git-media') in_temp_git do - append_file('testing1.mov', '1234567') - append_file('testing2.mov', '123456789') + append_file('testing1.x22', '1234567') + append_file('testing2.x22', '123456789') append_file('normal.txt', 'hello world') - append_file('.gitattributes', '*.mov filter=media') - `git config filter.media.clean "#{bin} clean"` - `git config filter.media.smudge "#{bin} smudge"` + append_file('.gitattributes', '*.x22 filter=media -crlf') + `git config filter.media.clean "#{bin} filter-clean"` + `git config filter.media.smudge "#{bin} filter-smudge"` yield end end @@ -42,4 +41,4 @@ def append_file(filename, content) def git(command) output = `git #{command} 2>/dev/null`.strip -end \ No newline at end of file +end