fuselage 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/.DS_Store +0 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +4 -0
  4. data/README.markdown +65 -0
  5. data/Rakefile +15 -0
  6. data/examples/authenticated.rb +21 -0
  7. data/examples/simple.rb +6 -0
  8. data/fuselage.gemspec +25 -0
  9. data/lib/.DS_Store +0 -0
  10. data/lib/fuselage/api.rb +100 -0
  11. data/lib/fuselage/base.rb +27 -0
  12. data/lib/fuselage/blob.rb +31 -0
  13. data/lib/fuselage/commit.rb +49 -0
  14. data/lib/fuselage/error.rb +28 -0
  15. data/lib/fuselage/reference.rb +50 -0
  16. data/lib/fuselage/repository.rb +111 -0
  17. data/lib/fuselage/tag.rb +44 -0
  18. data/lib/fuselage/tree.rb +41 -0
  19. data/lib/fuselage/user.rb +80 -0
  20. data/lib/fuselage/version.rb +3 -0
  21. data/lib/fuselage.rb +31 -0
  22. data/test/base_test.rb +17 -0
  23. data/test/blob_test.rb +29 -0
  24. data/test/commits_test.rb +30 -0
  25. data/test/references_test.rb +38 -0
  26. data/test/repository_test.rb +103 -0
  27. data/test/stubs/blobs/tester/new +16 -0
  28. data/test/stubs/blobs/tester/old +18 -0
  29. data/test/stubs/commits/tester/new +36 -0
  30. data/test/stubs/commits/tester/old +58 -0
  31. data/test/stubs/refs/tester/all +58 -0
  32. data/test/stubs/refs/tester/master +20 -0
  33. data/test/stubs/refs/tester/new +20 -0
  34. data/test/stubs/repos/coreycollins/tester/branches +27 -0
  35. data/test/stubs/repos/coreycollins/tester/commits +71 -0
  36. data/test/stubs/repos/coreycollins/tester/main +41 -0
  37. data/test/stubs/repos/coreycollins/tester/tags +40 -0
  38. data/test/stubs/repos/show/coreycollins +39 -0
  39. data/test/stubs/repos/show/coreycollins-private +39 -0
  40. data/test/stubs/repos/show/gitpilot +39 -0
  41. data/test/stubs/repos/show/gitpilot-private +120 -0
  42. data/test/stubs/tags/tester/new +27 -0
  43. data/test/stubs/tags/tester/old +27 -0
  44. data/test/stubs/trees/tester/new +26 -0
  45. data/test/stubs/trees/tester/old +25 -0
  46. data/test/stubs/users/coreycollins +34 -0
  47. data/test/stubs/users/coreycollins-private +34 -0
  48. data/test/stubs/users/emails +0 -0
  49. data/test/stubs/users/followers +25 -0
  50. data/test/stubs/users/following +25 -0
  51. data/test/stubs/users/repositories +40 -0
  52. data/test/test_helper.rb +103 -0
  53. data/test/user_test.rb +60 -0
  54. metadata +139 -0
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fuselage.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,65 @@
1
+ #Fuselage
2
+
3
+ Fuselage is a light weight Ruby wrapper for the Github v3 api. It was inspired by the Github v2 Ruby wrapper octopi.
4
+
5
+ It was created for Gitpilot. Check us out at: http://www.gitpilot.com
6
+
7
+ ##Credits
8
+
9
+ * Corey Collins
10
+ * JP Richardson
11
+
12
+ ##Install
13
+
14
+ Fuselage can easily be installed as a Ruby gem:
15
+
16
+ $ [sudo] gem install fuselage
17
+
18
+ ##Usage
19
+
20
+ To use fuselage just include it in your script:
21
+
22
+ require 'fuselage'
23
+
24
+ include Fuselage
25
+
26
+ ###Authenicated
27
+
28
+ If you have genereated a access token through github, then you can use the authenicated api with this method:
29
+
30
+ authenicated do
31
+ repo = Repository.find('private-repo')
32
+ end
33
+
34
+ ###Anonymous
35
+
36
+ Otherwise, if you are not authenticated there is no need to wrap your method call in the block. Like:
37
+
38
+ repo = Repository.find('public-repo')
39
+
40
+
41
+ ## API Completed
42
+
43
+ This is still a work in progress and not all of the api has been mapped yet. So far these have been mapped.
44
+
45
+ **1. Users**
46
+
47
+ **2. Repos**
48
+
49
+ **3. Git Data**
50
+
51
+ ##License
52
+
53
+ Copyright (c) 2011, Gitpilot LLC
54
+
55
+ Permission to use, copy, modify, and/or distribute this software for any
56
+ purpose with or without fee is hereby granted, provided that the above
57
+ copyright notice and this permission notice appear in all copies.
58
+
59
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
60
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
61
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
62
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
63
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
64
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
65
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'bundler'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ require 'rake/testtask'
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'lib' << 'test'
10
+ test.libs << File.dirname(__FILE__)
11
+ test.pattern = 'test/**/*_test.rb'
12
+ test.verbose = false
13
+ end
14
+
15
+ task :default => :test
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib cockpit]))
2
+
3
+ include Fuselage
4
+
5
+ access_token = "YOUR ACCESS TOKEN"
6
+
7
+ #Creating a branch on a private repo
8
+
9
+ authenticated(access_token) do
10
+
11
+ #Find the repo.
12
+ repo = Repository.find('private-repo')
13
+
14
+ # Get the most recent commit to point the reference to.
15
+ recent_commit = repo.most_recent_commit
16
+
17
+ #Create the reference
18
+ ref = Reference.create(repo.name, 'new-branch', recent_commit.sha)
19
+
20
+ puts ref
21
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib cockpit]))
2
+
3
+ include Fuselage
4
+
5
+ user = User.find 'coreycollins'
6
+ puts user
data/fuselage.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "fuselage/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "fuselage"
7
+ s.version = Fuselage::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Corey Collins"]
10
+ s.email = ["corey@gitpilot.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{LightWeight Github API v3 Wrapper}
13
+ s.description = %q{LightWeight Github API v3 Wrapper}
14
+
15
+ s.rubyforge_project = "fuselage"
16
+
17
+ s.add_development_dependency "rspec"
18
+ s.add_development_dependency "fakeweb"
19
+ s.add_dependency "httparty"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
data/lib/.DS_Store ADDED
Binary file
@@ -0,0 +1,100 @@
1
+ require 'singleton'
2
+
3
+ module Fuselage
4
+ # Dummy class, so AnonymousApi and AuthApi have somewhere to inherit from
5
+ class Api
6
+ attr_accessor :token, :read_only
7
+ end
8
+
9
+ # Used for accessing the Github API anonymously
10
+ class AnonymousApi < Api
11
+ include HTTParty
12
+ include Singleton
13
+ base_uri "https://api.github.com"
14
+
15
+ def read_only?
16
+ true
17
+ end
18
+
19
+ def auth_parameters
20
+ { }
21
+ end
22
+ end
23
+
24
+ class AuthApi < Api
25
+ include HTTParty
26
+ include Singleton
27
+ base_uri "https://api.github.com"
28
+
29
+ def read_only?
30
+ false
31
+ end
32
+
33
+ def auth_parameters
34
+ {:access_token => Api.me.token }
35
+ end
36
+ end
37
+
38
+ # This is the real API class.
39
+ #
40
+ # API requests are limited to 60 per minute.
41
+ #
42
+ # Sets up basic methods for accessing the API.
43
+ class Api
44
+ @@api = Fuselage::AnonymousApi.instance
45
+ @@authenticated = false
46
+
47
+ include Singleton
48
+
49
+ RETRYABLE_STATUS = [403]
50
+ MAX_RETRIES = 5
51
+ # Would be nice if cattr_accessor was available, oh well.
52
+
53
+ # We use this to check if we use the auth or anonymous api
54
+ def self.authenticated
55
+ @@authenticated
56
+ end
57
+
58
+ # We set this to true when the user has auth'd.
59
+ def self.authenticated=(value)
60
+ @@authenticated = value
61
+ end
62
+
63
+ # The API we're using
64
+ def self.api
65
+ @@api
66
+ end
67
+
68
+ class << self
69
+ alias_method :me, :api
70
+ end
71
+
72
+ # set the API we're using
73
+ def self.api=(value)
74
+ @@api = value
75
+ end
76
+
77
+ def get(path, params = {}, klass=nil)
78
+ resp = self.class.get(path, { :query => params.merge(auth_parameters) })
79
+ raise NotFound, klass || self.class if resp.code.to_i == 404
80
+ raise APIError,
81
+ "GitHub returned status #{resp.code}" unless resp.code.to_i == 200 || resp.code.to_i == 201
82
+ resp
83
+ end
84
+
85
+ def post(path, params = {}, klass=nil)
86
+ resp = self.class.post(path, { :query => auth_parameters, :body => params.to_json } )
87
+ raise NotFound, klass || self.class if resp.code.to_i == 404
88
+ raise APIError,
89
+ "GitHub returned status #{resp.code}" unless resp.code.to_i == 200 || resp.code.to_i == 201
90
+ resp
91
+ end
92
+
93
+ private
94
+
95
+ def method_missing(method, *args)
96
+ api.send(method, *args)
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,27 @@
1
+ module Fuselage
2
+ class Base
3
+
4
+ attr_accessor :api
5
+
6
+ def initialize(attributes={})
7
+ # Useful for finding out what attr_accessor needs for classes
8
+ # puts caller.first.inspect
9
+ # puts "#{self.class.inspect} #{attributes.keys.map { |s| s.to_sym }.inspect}"
10
+ attributes.each do |key, value|
11
+ method = "#{key}="
12
+ self.send(method, value) if respond_to? method
13
+ end
14
+ end
15
+
16
+ def self.get(path, params={})
17
+ response = Api.api.get(path, params, self)
18
+ response.parsed_response
19
+ end
20
+
21
+ def self.post(path, params={})
22
+ response = Api.api.post(path, params, self)
23
+ response.parsed_response
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ module Fuselage
2
+ class Blob < Base
3
+
4
+ attr_accessor :sha, :content, :encoding
5
+
6
+ # Find a blob
7
+ #
8
+ # examples:
9
+ # Blob.find('cockpit', '45f6d8e74e145b910be4e15f67ef3892fe7abb26')
10
+ def self.find(repo, sha, user=nil)
11
+ raise AuthenticationRequired unless Api.authenticated
12
+ user ||= User.current.login
13
+ Blob.new(get("/repos/#{user}/#{repo}/git/blobs/#{sha}").merge(:sha => sha))
14
+ end
15
+
16
+ # Create a blob
17
+ #
18
+ # Content must be in utf-8 encoding.
19
+ # TODO: Add suport for base-64.
20
+ #
21
+ # examples:
22
+ # Blob.create('cockpit', 'Some really cool data.')
23
+ def self.create(repo, content)
24
+ raise AuthenticationRequired unless Api.authenticated
25
+ params = {:content => content, :encoding => 'utf-8'}
26
+ user = User.current.login
27
+ Blob.new(post("/repos/#{user}/#{repo}/git/blobs", params))
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ module Fuselage
2
+ class Commit < Base
3
+
4
+ attr_accessor :sha, :message, :parents, :author, :url, :tree, :committer
5
+
6
+ # Find a commit
7
+ #
8
+ # examples:
9
+ # Blob.find('cockpit', '45f6d8e74e145b910be4e15f67ef3892fe7abb26')
10
+ def self.find(repo, sha, user=nil)
11
+ raise AuthenticationRequired unless Api.authenticated
12
+ user ||= User.current.login
13
+ Commit.new(get("/repos/#{user}/#{repo}/commits/#{sha}"))
14
+ end
15
+
16
+ # Create a commit
17
+ #
18
+ # Options:
19
+ # :author
20
+ # :name
21
+ # :date
22
+ # :email
23
+ # :committer
24
+ # :name
25
+ # :date
26
+ # :email
27
+ #
28
+ # examples:
29
+ # Commit.create('cockpit', 'This is a new commit', '45f6d8e74e145b910be4e15f67ef3892fe7abb26', ['45f6d8e74e145b910be4e15f67ef3892fe7abb26'])
30
+ #
31
+ # Commit.create('cockpit', 'Comit with author', '45f6d8e74e145b910be4e15f67ef3892fe7abb26', ['45f6d8e74e145b910be4e15f67ef3892fe7abb26'], {
32
+ # :author => {:name => 'Corey', :email => 'corey@gitpilot.com'}
33
+ # })
34
+ def self.create(repo, message, tree, parents=[], options={})
35
+ raise AuthenticationRequired unless Api.authenticated
36
+ params = {:message => message, :tree => tree, :parents => parents}.merge(options)
37
+ user = User.current.login
38
+ Commit.new(post("/repos/#{user}/#{repo}/git/commits", params))
39
+ end
40
+
41
+ def merge_attributes(attributes)
42
+ attributes.each do |key, value|
43
+ method = "#{key}="
44
+ self.send(method, value) if respond_to? method
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,28 @@
1
+ module Fuselage
2
+
3
+ class RegisterError < StandardError; end
4
+
5
+ class FormatError < StandardError
6
+ def initialize(f)
7
+ super("Got unexpected format (got #{f.first} for #{f.last})")
8
+ end
9
+ end
10
+
11
+ class AuthenticationRequired < StandardError
12
+ end
13
+
14
+ class APIError < StandardError
15
+ end
16
+
17
+ class InvalidLogin < StandardError
18
+ end
19
+
20
+ class ArgumentMustBeHash < Exception; end
21
+
22
+ class NotFound < Exception
23
+ def initialize(klass)
24
+ super "The #{klass.to_s.split("::").last} could not be found or created. It could be private."
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,50 @@
1
+ module Fuselage
2
+ class Reference < Base
3
+
4
+ attr_accessor :ref, :url, :object
5
+
6
+ # Find a reference
7
+ #
8
+ # ref must have 'heads/' in front of branch name
9
+ #
10
+ # examples:
11
+ # Reference.find('cockpit', 'hads/master')
12
+ def self.find(repo, ref, user=nil)
13
+ raise AuthenticationRequired unless Api.authenticated
14
+ user ||= User.current.login
15
+ Reference.new(get("/repos/#{user}/#{repo}/git/refs/#{ref}"))
16
+ end
17
+
18
+ # Finds all the refs for a given repo.
19
+ def self.find_all(repo, user=nil)
20
+ raise AuthenticationRequired unless Api.authenticated
21
+ user ||= User.current.login
22
+ refs = []
23
+ get("/repos/#{user}/#{repo}/git/refs").each { |r| refs << Reference.new(r) }
24
+ refs
25
+ end
26
+
27
+ def self.create(repo, ref, sha)
28
+ raise AuthenticationRequired unless Api.authenticated
29
+ params = {:ref => ref, :sha => sha}
30
+ user = User.current.login
31
+ Reference.new(post("/repos/#{user}/#{repo}/git/refs", params))
32
+ end
33
+
34
+ def self.update(repo, ref, sha, force=true, user=nil)
35
+ raise AuthenticationRequired unless Api.authenticated
36
+ params = {:force => force, :sha => sha}
37
+ user ||= User.current.login
38
+ Reference.new(post("/repos/#{user}/#{repo}/git/refs/#{ref}", params))
39
+ end
40
+
41
+ def sha
42
+ object['sha'] if object
43
+ end
44
+
45
+ def to_s
46
+ ref
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,111 @@
1
+ module Fuselage
2
+ class Repository < Base
3
+
4
+ attr_accessor :description, :url, :forks, :name, :homepage, :watchers,
5
+ :owner, :private, :fork, :open_issues, :pledgie, :size
6
+
7
+
8
+ # Finds a repo with current authenticated user
9
+ #
10
+ def self.find(repo, options={})
11
+ options = {:type => 'all'}.merge(options)
12
+ if options[:user]
13
+ Repository.new(get("/repos/#{options[:user]}/#{repo}", {:type => options[:type]}))
14
+ else
15
+ raise AuthenticationRequired unless Api.authenticated
16
+ Repository.new(get("/repos/#{User.current.login}/#{repo}", {:type => options[:type]}))
17
+ end
18
+ end
19
+
20
+ # Finds all public repos identified by the given username
21
+ #
22
+ def self.find_all(options={})
23
+ options = {:type => 'all'}.merge(options)
24
+ repos = []
25
+ if options[:user]
26
+ get("/users/#{options[:user]}/repos", {:type => options[:type]}).each { |r| repos << Repository.new(r) }
27
+ else
28
+ raise AuthenticationRequired unless Api.authenticated
29
+ get("/user/repos", {:type => options[:type]}).each { |r| repos << Repository.new(r) }
30
+ end
31
+ repos
32
+ end
33
+
34
+ # Finds all public repos identified by the given organization
35
+ #
36
+ def self.find_by_organization(organization, options={})
37
+ options = {:type => 'all'}.merge(options)
38
+ repos = []
39
+ get("/orgs/#{organization}/repos", {:type => options[:type]}).each { |r| repos << Repository.new(r) }
40
+ repos
41
+ end
42
+
43
+ def self.create(name, options={})
44
+ raise AuthenticationRequired unless Api.authenticated
45
+ Repository.new(post('/user/repos', {:name => name}.merge(options)))
46
+ end
47
+
48
+ def tags
49
+ raise AuthenticationRequired unless Api.authenticated
50
+ tags = []
51
+ Repository.get("/repos/#{User.current.login}/#{self.name}/tags").each do |t|
52
+ tag = Tag.new
53
+ tag.tag = t['name']
54
+ if t['commit']
55
+ tag.object = t['commit']
56
+ tag.object['type'] = 'commit'
57
+ end
58
+ tags << tag
59
+ end
60
+ tags
61
+ end
62
+
63
+ def branches
64
+ raise AuthenticationRequired unless Api.authenticated
65
+ branches = []
66
+ Repository.get("/repos/#{User.current.login}/#{self.name}/branches").each do |b|
67
+ branch = Reference.new
68
+ branch.ref = 'ref/heads/' + b['name']
69
+ branch.url = b['url']
70
+ if b['commit']
71
+ branch.object = b['commit']
72
+ branch.object['type'] = 'commit'
73
+ end
74
+ branches << branch
75
+ end
76
+ branches
77
+ end
78
+
79
+ def commits(options={})
80
+ raise AuthenticationRequired unless Api.authenticated
81
+ commits = []
82
+ Repository.get("/repos/#{User.current.login}/#{self.name}/commits", options).each do |c|
83
+ commit = Commit.new(c)
84
+ if c['commit']
85
+ commit.merge_attributes(c['commit'])
86
+ end
87
+ commits << commit
88
+ end
89
+ commits
90
+ end
91
+
92
+ def most_recent_commit(ref_sha)
93
+ commits = self.commits(:sha => ref_sha)
94
+ commits.first
95
+ end
96
+
97
+ def create_branch(name, parent_sha)
98
+ Reference.create(self.name, "refs/heads/#{name}", parent_sha)
99
+ end
100
+
101
+ def to_s
102
+ name
103
+ end
104
+
105
+ def pp
106
+
107
+ end
108
+
109
+ end
110
+ end
111
+
@@ -0,0 +1,44 @@
1
+ module Fuselage
2
+ class Tag < Base
3
+ attr_accessor :tag, :sha, :message, :tagger, :object, :url
4
+
5
+ # Find a tag
6
+ #
7
+ # examples:
8
+ # Tag.find('cockpit', '45f6d8e74e145b910be4e15f67ef3892fe7abb26')
9
+ def self.find(repo, sha, user=nil)
10
+ raise AuthenticationRequired unless Api.authenticated
11
+ user ||= User.current.login
12
+ Tag.new(get("/repos/#{user}/#{repo}/git/tags/#{sha}"))
13
+ end
14
+
15
+ # Create a tag
16
+ #
17
+ #
18
+ # Options:
19
+ # :type, values: 'commit', 'tree', and 'blob'. default is commit
20
+ # :tagger
21
+ # :name
22
+ # :date
23
+ # :email
24
+ #
25
+ # examples:
26
+ # Tag.create('cockpit', v1.0', 'New tag', '45f6d8e74e145b910be4e15f67ef3892fe7abb26')
27
+ #
28
+ # Commit.create('cockpit', v1.0', 'New tag', '45f6d8e74e145b910be4e15f67ef3892fe7abb26', {
29
+ # :tagger => {:name => 'Corey', :email => 'corey@gitpilot.com'}
30
+ # })
31
+ def self.create(repo, tag, message, object, options={})
32
+ raise AuthenticationRequired unless Api.authenticated
33
+ options = {:type => 'commit'}.merge(options)
34
+ params = {:tag => tag, :message => message, :object => object}.merge(options)
35
+ user = User.current.login
36
+ Tag.new(post("/repos/#{user}/#{repo}/git/blobs", params))
37
+ end
38
+
39
+ def to_s
40
+ tag
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ module Fuselage
2
+ class Tree < Base
3
+
4
+ attr_accessor :sha, :url, :tree, :path, :mode
5
+
6
+ # Find a tree
7
+ #
8
+ # examples:
9
+ # Tree.find('cockpit', '45f6d8e74e145b910be4e15f67ef3892fe7abb26')
10
+ def self.find(repo, sha, user=nil)
11
+ raise AuthenticationRequired unless Api.authenticated
12
+ user ||= User.current.login
13
+ Commit.new(get("/repos/#{user}/#{repo}/trees/#{sha}"))
14
+ end
15
+
16
+ # Create a tree
17
+ #
18
+ # Tree Hash:
19
+ # :path => 'file',
20
+ # :mode => '100644', refer to http://developer.github.com/v3/git/trees/ for modes.
21
+ # :type => 'commit', values: 'commit', 'tree', and 'blob'.
22
+ # :sha => '45f6d8e74e145b910be4e15f67ef3892fe7abb26'
23
+ # or
24
+ # :content => 'Some UTF-8 Encoded Content'
25
+ #
26
+ # Options:
27
+ # :type, values: 'commit', 'tree', and 'blob'. default is commit
28
+ # :tagger
29
+ # :name
30
+ # :date
31
+ # :email
32
+ #
33
+ def self.create(repo, tree_hashes=[], options={})
34
+ raise AuthenticationRequired unless Api.authenticated
35
+ params = {:tree => tree_hashes }.merge(options)
36
+ user = User.current.login
37
+ Tree.new(post("/repos/#{user}/#{repo}/git/trees", params))
38
+ end
39
+
40
+ end
41
+ end