git_hub 0.2.10 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/README.rdoc +43 -7
  2. data/Rakefile +1 -0
  3. data/VERSION +1 -1
  4. data/bin/git_hub +1 -0
  5. data/git_hub.gemspec +36 -32
  6. data/lib/git_hub.rb +3 -5
  7. data/lib/git_hub/api.rb +8 -13
  8. data/lib/git_hub/base.rb +44 -42
  9. data/lib/git_hub/commit.rb +6 -4
  10. data/lib/git_hub/extensions.rb +25 -0
  11. data/lib/git_hub/repo.rb +21 -24
  12. data/lib/git_hub/user.rb +8 -6
  13. data/spec/git_hub/api_spec.rb +21 -0
  14. data/spec/git_hub/base_spec.rb +5 -5
  15. data/spec/git_hub/commit_spec.rb +2 -2
  16. data/spec/git_hub/extensions_spec.rb +55 -0
  17. data/spec/git_hub/repo_spec.rb +51 -40
  18. data/spec/git_hub/user_spec.rb +26 -20
  19. data/spec/spec_helper.rb +31 -46
  20. data/spec/stubs/{api_route_error.res → yaml/api_route_error.res} +0 -0
  21. data/spec/stubs/{commits → yaml/commits}/list/joe007/fine_repo/master.res +0 -0
  22. data/spec/stubs/{commits → yaml/commits}/list/joe007/fine_repo/master/README.res +0 -0
  23. data/spec/stubs/{commits → yaml/commits}/show/joe007/fine_repo/3a70f86293b719f193f778a8710b1f83f2f7bf38.res +0 -0
  24. data/spec/stubs/{commits → yaml/commits}/show/joe007/fine_repo/5e61f0687c40ca48214d09dc7ae2d0d0d8fbfeb8.res +0 -0
  25. data/spec/stubs/{commits → yaml/commits}/show/joe007/fine_repo/f7f5dddaa37deacc83f1f56876e2b135389d03ab.res +0 -0
  26. data/spec/stubs/{repos → yaml/repos}/create.1.res +0 -0
  27. data/spec/stubs/{repos → yaml/repos}/create.2.res +0 -0
  28. data/spec/stubs/{repos → yaml/repos}/create.3.res +0 -0
  29. data/spec/stubs/{repos → yaml/repos}/create.4.res +0 -0
  30. data/spec/stubs/{repos → yaml/repos}/delete/new_repo.1.res +0 -0
  31. data/spec/stubs/{repos → yaml/repos}/delete/new_repo.2.res +0 -0
  32. data/spec/stubs/{repos → yaml/repos}/delete/new_repo.res +0 -0
  33. data/spec/stubs/{repos → yaml/repos}/search/fine+repo.res +0 -0
  34. data/spec/stubs/{repos → yaml/repos}/search/joe+repo.res +0 -0
  35. data/spec/stubs/yaml/repos/show/invalid_github_user/err_repo.res +14 -0
  36. data/spec/stubs/{repos → yaml/repos}/show/joe007.res +0 -0
  37. data/spec/stubs/{repos → yaml/repos}/show/joe007/err_repo.res +0 -0
  38. data/spec/stubs/{repos → yaml/repos}/show/joe007/fine_repo.res +0 -0
  39. data/spec/stubs/{repos → yaml/repos}/show/joe007/fine_repo/branches.res +0 -0
  40. data/spec/stubs/{repos → yaml/repos}/show/joe007/fine_repo/tags.res +0 -0
  41. data/spec/stubs/{repos → yaml/repos}/show/joe007/new_repo.res +0 -0
  42. data/spec/stubs/{user → yaml/user}/follow/arvicco.res +0 -0
  43. data/spec/stubs/{user → yaml/user}/search/joe+007.res +0 -0
  44. data/spec/stubs/{user → yaml/user}/show/arvicco.res +0 -0
  45. data/spec/stubs/{user/show/joe_is_not_github_user.res → yaml/user/show/invalid_github_user.res} +7 -3
  46. data/spec/stubs/{user → yaml/user}/show/joe007.auth.res +0 -0
  47. data/spec/stubs/{user → yaml/user}/show/joe007.res +0 -0
  48. data/spec/stubs/{user → yaml/user}/show/joe007/followers.res +0 -0
  49. data/spec/stubs/{user → yaml/user}/show/joe007/following.empty.res +0 -0
  50. data/spec/stubs/{user → yaml/user}/show/joe007/following.res +0 -0
  51. metadata +36 -32
@@ -18,29 +18,58 @@ Contributors always welcome!
18
18
  require 'git_hub'
19
19
  include GitHub
20
20
 
21
+ === General notes
22
+ There is more than one way to name things, for example when looking for repository,
23
+ following option keys have the same effect - :repository, :repo, :project.
24
+
25
+ Most methods just retrieve the state of remote github objects. Any method that intends
26
+ to CHANGE the state of remote objects, create or delete remote objects is followed by
27
+ exclamation (create!, delete!, set!, add!, etc) and requires authentication.
28
+
29
+ === Authentication
30
+
31
+ === Repositories API
21
32
  Find existing repos:
22
33
  repo = Repo.find(:user=>user_name, :repo=>repo_name)
23
34
  repos = Repo.find(:user=>user_name)
24
35
  search_repos = Repo.find(:query=>['search','terms'])
25
36
 
37
+ Create new repo or delete existing repo (need to authenticate with your github credentials first)
38
+ Api.auth = {:user=>user_name, :token=>token}
39
+ new_repo = Repo.create!(:name=>repo_name, :desc=>'Description', :homepage=>'http://your_page.org', :private=> false)
40
+ new_repo.delete!
41
+
26
42
  Retrieve tags, branches and commits for a repo:
27
43
  puts repo.tags['v0.1.0'].committer
28
44
  puts repo.branches['master'].committed_date
29
- repo.commits.each {|commit| p commit.author}
45
+ repo.commits(:branch=>'left').each {|commit| p commit.author}
46
+
47
+ #tags and #branches return Hash of (latest) commits, with tag/branch name as keys.
48
+ #commits returns an Array of commit objects for a given repo. If no options given,
49
+ a whole set of commits for this repo is returned (this takes a while to load).
50
+
51
+ === Commits API
52
+ You can work either with commit objects either directly, or via Repo API
30
53
 
31
- Retrieve info for a specific commit:
54
+ Retrieve info for a specific commit or a set of commits:
55
+ commit = Commit.find(:user=>user_name, :repo=>repo_name, :sha=>'commit_sha')
32
56
  commits = Commit.find(:user=>user_name, :repo=>repo_name, :branch=>'master')
33
57
  commits = Commit.find(:user=>user_name, :repo=>repo_name, :branch=>'master', :path=>'README.rdoc')
34
- commit = Commit.find(:user=>user_name, :repo=>repo_name, :sha=>'commit_sha')
35
58
  # or, if repo is already retrieved:
36
59
  commit = repo.commits.last
37
60
  commit = repo.tags['v0.1.0']
38
61
  commit = repo.branches['master'] # returns most recent commit for a branch
39
62
 
40
- Create new repo or delete existing repo (need to authenticate with your github credentials first)
41
- Api.auth = {:user=>user_name, :token=>token}
42
- new_repo = Repo.create(:name=>repo_name, :desc=>'Description', :homepage=>'http://your_page.org', :private=> false)
43
- new_repo.delete
63
+ === Users API
64
+ Find existing repos:
65
+ user = User.find(:user=>user_name)
66
+ search_users = User.find(:query=>['search','terms'])
67
+
68
+ Retrieve/manage user's network:
69
+ user.followers.each {|githubber| p githubber.fullname}
70
+ user.following.each {|githubber| p githubber.fullname}
71
+ user.follow! :user=>githubber_name
72
+ user.unfollow! :user=>githubber_name
44
73
 
45
74
  == REQUIREMENTS:
46
75
 
@@ -50,6 +79,13 @@ Create new repo or delete existing repo (need to authenticate with your github c
50
79
 
51
80
  $ sudo gem install git_hub
52
81
 
82
+ == PRIOR ART:
83
+
84
+ Le-Git - http://github.com/technicalpickles/le-git
85
+ Octopi - http://github.com/fcoury/octopi
86
+ Github-gem - http://github.com/defunkt/github-gem
87
+ Github-control - http://github.com/halorgium/github-control
88
+
53
89
  == LICENSE:
54
90
 
55
91
  Copyright (c) 2009 Arvicco. See LICENSE for details
data/Rakefile CHANGED
@@ -12,6 +12,7 @@ begin
12
12
  gem.authors = ["arvicco"]
13
13
  gem.add_development_dependency "rspec", ">= 1.2.9"
14
14
  gem.add_development_dependency "cucumber", ">= 0"
15
+ gem.executables = ['git_hub']
15
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
17
  end
17
18
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.10
1
+ 0.3.0
@@ -3,4 +3,5 @@
3
3
  require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib git_hub]))
4
4
 
5
5
  # Put your code here
6
+ puts 'Nothing interesting here yet'
6
7
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{git_hub}
8
- s.version = "0.2.10"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["arvicco"]
12
- s.date = %q{2010-01-14}
12
+ s.date = %q{2010-01-16}
13
13
  s.default_executable = %q{git_hub}
14
14
  s.description = %q{Simple interface to github API}
15
15
  s.email = %q{arvitallian@gmail.com}
@@ -32,46 +32,49 @@ Gem::Specification.new do |s|
32
32
  "lib/git_hub/api.rb",
33
33
  "lib/git_hub/base.rb",
34
34
  "lib/git_hub/commit.rb",
35
+ "lib/git_hub/extensions.rb",
35
36
  "lib/git_hub/repo.rb",
36
37
  "lib/git_hub/user.rb",
37
38
  "spec/git_hub/api_spec.rb",
38
39
  "spec/git_hub/base_spec.rb",
39
40
  "spec/git_hub/commit_spec.rb",
41
+ "spec/git_hub/extensions_spec.rb",
40
42
  "spec/git_hub/repo_spec.rb",
41
43
  "spec/git_hub/user_spec.rb",
42
44
  "spec/spec.opts",
43
45
  "spec/spec_helper.rb",
44
- "spec/stubs/api_route_error.res",
45
- "spec/stubs/commits/list/joe007/fine_repo/master.res",
46
- "spec/stubs/commits/list/joe007/fine_repo/master/README.res",
47
- "spec/stubs/commits/show/joe007/fine_repo/3a70f86293b719f193f778a8710b1f83f2f7bf38.res",
48
- "spec/stubs/commits/show/joe007/fine_repo/5e61f0687c40ca48214d09dc7ae2d0d0d8fbfeb8.res",
49
- "spec/stubs/commits/show/joe007/fine_repo/f7f5dddaa37deacc83f1f56876e2b135389d03ab.res",
50
46
  "spec/stubs/http/users/follow.res",
51
- "spec/stubs/repos/create.1.res",
52
- "spec/stubs/repos/create.2.res",
53
- "spec/stubs/repos/create.3.res",
54
- "spec/stubs/repos/create.4.res",
55
- "spec/stubs/repos/delete/new_repo.1.res",
56
- "spec/stubs/repos/delete/new_repo.2.res",
57
- "spec/stubs/repos/delete/new_repo.res",
58
- "spec/stubs/repos/search/fine+repo.res",
59
- "spec/stubs/repos/search/joe+repo.res",
60
- "spec/stubs/repos/show/joe007.res",
61
- "spec/stubs/repos/show/joe007/err_repo.res",
62
- "spec/stubs/repos/show/joe007/fine_repo.res",
63
- "spec/stubs/repos/show/joe007/fine_repo/branches.res",
64
- "spec/stubs/repos/show/joe007/fine_repo/tags.res",
65
- "spec/stubs/repos/show/joe007/new_repo.res",
66
- "spec/stubs/user/follow/arvicco.res",
67
- "spec/stubs/user/search/joe+007.res",
68
- "spec/stubs/user/show/arvicco.res",
69
- "spec/stubs/user/show/joe007.auth.res",
70
- "spec/stubs/user/show/joe007.res",
71
- "spec/stubs/user/show/joe007/followers.res",
72
- "spec/stubs/user/show/joe007/following.empty.res",
73
- "spec/stubs/user/show/joe007/following.res",
74
- "spec/stubs/user/show/joe_is_not_github_user.res"
47
+ "spec/stubs/yaml/api_route_error.res",
48
+ "spec/stubs/yaml/commits/list/joe007/fine_repo/master.res",
49
+ "spec/stubs/yaml/commits/list/joe007/fine_repo/master/README.res",
50
+ "spec/stubs/yaml/commits/show/joe007/fine_repo/3a70f86293b719f193f778a8710b1f83f2f7bf38.res",
51
+ "spec/stubs/yaml/commits/show/joe007/fine_repo/5e61f0687c40ca48214d09dc7ae2d0d0d8fbfeb8.res",
52
+ "spec/stubs/yaml/commits/show/joe007/fine_repo/f7f5dddaa37deacc83f1f56876e2b135389d03ab.res",
53
+ "spec/stubs/yaml/repos/create.1.res",
54
+ "spec/stubs/yaml/repos/create.2.res",
55
+ "spec/stubs/yaml/repos/create.3.res",
56
+ "spec/stubs/yaml/repos/create.4.res",
57
+ "spec/stubs/yaml/repos/delete/new_repo.1.res",
58
+ "spec/stubs/yaml/repos/delete/new_repo.2.res",
59
+ "spec/stubs/yaml/repos/delete/new_repo.res",
60
+ "spec/stubs/yaml/repos/search/fine+repo.res",
61
+ "spec/stubs/yaml/repos/search/joe+repo.res",
62
+ "spec/stubs/yaml/repos/show/invalid_github_user/err_repo.res",
63
+ "spec/stubs/yaml/repos/show/joe007.res",
64
+ "spec/stubs/yaml/repos/show/joe007/err_repo.res",
65
+ "spec/stubs/yaml/repos/show/joe007/fine_repo.res",
66
+ "spec/stubs/yaml/repos/show/joe007/fine_repo/branches.res",
67
+ "spec/stubs/yaml/repos/show/joe007/fine_repo/tags.res",
68
+ "spec/stubs/yaml/repos/show/joe007/new_repo.res",
69
+ "spec/stubs/yaml/user/follow/arvicco.res",
70
+ "spec/stubs/yaml/user/search/joe+007.res",
71
+ "spec/stubs/yaml/user/show/arvicco.res",
72
+ "spec/stubs/yaml/user/show/invalid_github_user.res",
73
+ "spec/stubs/yaml/user/show/joe007.auth.res",
74
+ "spec/stubs/yaml/user/show/joe007.res",
75
+ "spec/stubs/yaml/user/show/joe007/followers.res",
76
+ "spec/stubs/yaml/user/show/joe007/following.empty.res",
77
+ "spec/stubs/yaml/user/show/joe007/following.res"
75
78
  ]
76
79
  s.homepage = %q{http://github.com/arvicco/git_hub}
77
80
  s.rdoc_options = ["--charset=UTF-8"]
@@ -82,6 +85,7 @@ Gem::Specification.new do |s|
82
85
  "spec/git_hub/api_spec.rb",
83
86
  "spec/git_hub/base_spec.rb",
84
87
  "spec/git_hub/commit_spec.rb",
88
+ "spec/git_hub/extensions_spec.rb",
85
89
  "spec/git_hub/repo_spec.rb",
86
90
  "spec/git_hub/user_spec.rb",
87
91
  "spec/spec_helper.rb"
@@ -27,11 +27,9 @@ module GitHub
27
27
  # in. Optionally, a specific _directory_ name can be passed in such that
28
28
  # the _filename_ does not have to be equivalent to the directory.
29
29
  #
30
- def self.require_all_libs_relative_to( fname, dir = nil )
31
- dir ||= ::File.basename(fname, '.*')
32
- search_me = ::File.expand_path(::File.join(::File.dirname(fname), dir, '**', '*.rb'))
33
-
34
- Dir.glob(search_me).sort.each {|rb| require rb}
30
+ def self.require_all_libs_relative_to( fname )
31
+ ruby_files = ::File.expand_path(::File.join(::File.dirname(fname), '**', '*.rb'))
32
+ Dir.glob(ruby_files).sort.each {|rb| require rb}
35
33
  end
36
34
 
37
35
  end # module GitHub
@@ -15,29 +15,24 @@ module GitHub
15
15
  auth != {}
16
16
  end
17
17
 
18
+ #TODO: need to fix it in terms of options and add tests
18
19
  def ensure_auth opts ={}
19
20
  return if authenticated?
20
- @auth = {'login'=>opts[:login], 'token'=>opts[:token]}
21
- raise("Authentication failed") unless authenticated?
21
+ login = opts[:login]
22
+ token = opts[:token]
23
+ raise("Authentication failed") unless login && token
24
+ @auth = {'login'=>login, 'token'=>token}
22
25
  end
23
26
 
24
- # Turns string into appropriate class constant, returns nil if class not found
25
- def classify name
26
- klass = name.split("::").inject(Kernel) {|klass, const_name| klass.const_get const_name }
27
- klass.is_a?(Class) ? klass : nil
28
- rescue NameError
29
- nil
30
- end
31
-
32
- def request verb, url, params = {}
33
- method = classify('Net::HTTP::' + verb.to_s.capitalize)
27
+ def request verb, url, data = {}
28
+ method = ('Net::HTTP::' + verb.to_s.capitalize).to_class
34
29
  uri = URI.parse url
35
30
  server = Net::HTTP.new(uri.host, uri.port)
36
31
  server.use_ssl = (uri.scheme == 'https')
37
32
  server.verify_mode = OpenSSL::SSL::VERIFY_NONE if server.use_ssl?
38
33
  server.start do |http|
39
34
  req = method.new(uri.path)
40
- req.form_data = params.merge(auth)
35
+ req.form_data = data.merge(auth)
41
36
  http.request(req)
42
37
  end
43
38
  end
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
 
3
3
  module GitHub
4
+ API = Api.instance
4
5
  class Base
5
6
 
6
7
  def initialize(attributes={})
@@ -15,11 +16,9 @@ module GitHub
15
16
  end
16
17
 
17
18
  class << self
18
- def request verb, uri, params = {}
19
+ def request verb, uri, data = {}
19
20
  full_uri = uri[0] == '/' ? base_uri+uri : uri
20
- #p "request: #{verb} #{full_uri} #{params}"
21
- res = api.request verb, full_uri, params
22
- #p "response: #{res}: #{res.code}: #{res.http_version}: #{res.message}", res.body
21
+ res = API.request verb, full_uri, data
23
22
  if res.respond_to?(:content_type, :body) && res.content_type =~ /application\/x-yaml/
24
23
  YAML::load(res.body)
25
24
  else
@@ -27,22 +26,18 @@ module GitHub
27
26
  end
28
27
  end
29
28
 
30
- def get uri, params ={}
31
- request :get, uri, params
29
+ def get uri, data = {}
30
+ request :get, uri, data
32
31
  end
33
32
 
34
- def post uri, params = {}
35
- request :post, uri, params
33
+ def post uri, data = {}
34
+ request :post, uri, data
36
35
  end
37
36
 
38
- def api
39
- Api.instance
40
- end
41
-
42
- def set_resource base_uri, singulars, plurals
37
+ def set_resource base_uri, singular, plural
43
38
  @base_uri = base_uri
44
- @singulars = [singulars].flatten
45
- @plurals = [plurals].flatten
39
+ @singular = singular.to_s
40
+ @plural = plural.to_s
46
41
  end
47
42
 
48
43
  def base_uri
@@ -61,56 +56,63 @@ module GitHub
61
56
 
62
57
  private
63
58
 
64
- # extracts arguments described by *args from an opts Hash
59
+ # matches arguments supplied by args Array to parameters specified by *params Array of Symbols
65
60
  # TODO: replace opts[:name] with class-specific opts[:@singular]?
66
- def extract(opts, *args)
67
- raise "Expected options Hash, got #{opts}" unless opts.kind_of? Hash
68
- args.map do |arg|
69
- opts[arg] || opts[arg.to_sym] || case arg.to_sym
61
+ def extract(args, *params)
62
+ args, opts = args.args_and_opts
63
+ name = extract_value opts, :name
64
+ opts.merge!(@singular.to_sym => name ) if name
65
+ params.map do |param| # for every symbol in params Array:
66
+ arg = args.next rescue nil # try to assign sequential argument from args
67
+ arg ||= extract_value opts, param # try to assign named argument from opts
68
+ arg || case param # assign defaults if no other value found
70
69
  when :user
71
- opts[:owner] || opts[:username] || opts[:login] || api.auth['login']
72
- when :repo
73
- opts[:repository] || opts[:name] || opts[:project]
74
- when :sha
75
- opts[:hash] || opts[:object_id] || opts[:id]
76
- when :desc
77
- opts[:description] || opts[:descr]
78
- when :query
79
- opts[:search]
70
+ API.auth['login']
80
71
  when :branch
81
72
  'master'
82
73
  when :public
83
- !opts[:private] unless opts[:public] == false
74
+ !extract_value(opts, :private) unless arg == false
84
75
  else
85
- nil
76
+ nil # no default found, parameter is nil
86
77
  end
87
78
  end
88
79
  end
89
80
 
81
+ NICKNAMES = { :user => [:owner, :username, :login],
82
+ :repo => [:repository, :project],
83
+ :sha => [:id, :object_id, :hash],
84
+ :desc => [:description, :descr],
85
+ :query => :search }
86
+
87
+ # extracts from opts value indexed by param or any of its nicknames
88
+ def extract_value opts, param
89
+ nicks = [param, NICKNAMES[param]].flatten.compact
90
+ opts.values_at(*nicks+nicks.map(&:to_s)).compact.first
91
+ end
92
+
90
93
  # Creates single instance or Array of instances for a given Hash of
91
94
  # attribute Hash(es), returns original Hash if unsuccessful
92
95
  def instantiate hash, extra_attributes={}
93
96
  return hash unless hash.kind_of? Hash
94
- if init = hash.values_at(*@singulars).compact.first
97
+ # init = hash.values_at(*@singulars).compact.first
98
+ init = hash[@singular]
99
+ inits = hash[@plural]
100
+ if init
95
101
  new init.merge extra_attributes
96
- elsif inits = hash.values_at(*@plurals).compact.first
97
- inits.map {|init| new init.merge extra_attributes}
102
+ elsif inits
103
+ inits.map {|each| new each.merge extra_attributes}
98
104
  else
99
105
  hash
100
106
  end
101
107
  end
102
108
  end
103
109
 
104
- def get uri, params ={}
105
- self.class.get uri, params
106
- end
107
-
108
- def post uri, params ={}
109
- self.class.post uri, params
110
+ def get uri, data = {}
111
+ self.class.get uri, data
110
112
  end
111
113
 
112
- def api
113
- self.class.api
114
+ def post uri, data = {}
115
+ self.class.post uri, data
114
116
  end
115
117
 
116
118
  def to_s
@@ -3,17 +3,19 @@ module GitHub
3
3
 
4
4
  set_resource 'http://github.com/api/v2/yaml/commits', 'commit', 'commits'
5
5
 
6
- attr_accessor :id, :author, :committer, :parents, :url, :committed_date, :authored_date, :message, :tree,
6
+ attr_accessor :id, :author, :committer, :parents, :url, :committed, :authored, :message, :tree,
7
7
  # retrieving commit for a specific sha - "/show/:user/:repo/:sha" adds:
8
8
  :added, :modified, :removed,
9
9
  # extra attributes:
10
10
  :user, :repo
11
11
 
12
- aliases_for :id => [:sha, :name]
12
+ aliases_for :id => [:sha, :name], :committed => :committed_date, :authored => :authored_date
13
13
 
14
14
  def initialize(opts)
15
15
  super
16
16
  raise "Unable to initialize #{self.class} without id(sha)" unless sha
17
+ @committed = Time.parse(@committed) unless @committed.is_a?(Time)
18
+ @authored = Time.parse(@authored) unless @authored.is_a?(Time)
17
19
  end
18
20
 
19
21
  class << self
@@ -23,8 +25,8 @@ module GitHub
23
25
  # :branch:: Only commits for specific branch - default 'master'
24
26
  # :path:: Only commits for specific path
25
27
  # :sha/:id:: Only one commit with specific id (sha)
26
- def find(opts)
27
- user, repo, branch, sha, path = extract opts, :user, :repo, :branch, :sha, :path
28
+ def find( *args )
29
+ user, repo, branch, sha, path = extract args, :user, :repo, :branch, :sha, :path
28
30
  repo_given = branch && user && repo
29
31
  path = if sha && repo_given
30
32
  "/show/#{user}/#{repo}/#{sha}"
@@ -0,0 +1,25 @@
1
+ class String
2
+ # Turns string into appropriate class constant, returns nil if class not found
3
+ def to_class
4
+ klass = self.split("::").inject(Kernel) do |namespace, const|
5
+ const == '' ? namespace : namespace.const_get(const)
6
+ end
7
+ klass.is_a?(Class) ? klass : nil
8
+ rescue NameError
9
+ nil
10
+ end
11
+ end
12
+
13
+ class Array
14
+
15
+ # Splits (arguments) Array into two components: enum for args and options Hash
16
+ # options Hash (if any) should be the last component of Array
17
+ def args_and_opts
18
+ opts = self.last
19
+ if opts.is_a?(Hash)
20
+ [self[0..-2].to_enum, opts]
21
+ else
22
+ [self.to_enum, {}]
23
+ end
24
+ end
25
+ end