octopi 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ examples/github.yml
2
+ rdoc/
3
+ pkg/
data/README.rdoc CHANGED
@@ -4,8 +4,11 @@ Octopi is a Ruby interface to GitHub API v2 (http://develop.github.com).
4
4
 
5
5
  To install it as a Gem, just run:
6
6
 
7
- $ sudo gem install fcoury-octopi --source http://gems.github.com
7
+ $ sudo gem install octopi
8
8
 
9
+ Get notifications via Twitter, following @octopi_gem:
10
+ http://twitter.com/octopi_gem
11
+
9
12
  == Authenticated Usage
10
13
 
11
14
  === Seamless authentication using .gitconfig defaults
data/Rakefile ADDED
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "octopi"
8
+ gem.summary = %Q{A Ruby interface to GitHub API v2}
9
+ gem.email = "felipe.coury@gmail.com"
10
+ gem.homepage = "http://github.com/fcoury/octopi"
11
+ gem.authors = ["Felipe Coury"]
12
+ gem.rubyforge_project = "octopi"
13
+
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ begin
21
+ require 'rake/contrib/sshpublisher'
22
+ namespace :rubyforge do
23
+
24
+ desc "Release gem and RDoc documentation to RubyForge"
25
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
26
+
27
+ namespace :release do
28
+ desc "Publish RDoc to RubyForge."
29
+ task :docs => [:rdoc] do
30
+ config = YAML.load(
31
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
32
+ )
33
+
34
+ host = "#{config['username']}@rubyforge.org"
35
+ remote_dir = "/var/www/gforge-projects/octopi/"
36
+ local_dir = 'rdoc'
37
+
38
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
39
+ end
40
+ end
41
+ end
42
+ rescue LoadError
43
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
44
+ end
45
+
46
+ require 'rake/testtask'
47
+ Rake::TestTask.new(:test) do |test|
48
+ test.libs << 'lib' << 'test'
49
+ test.pattern = 'test/**/*_test.rb'
50
+ test.verbose = false
51
+ end
52
+
53
+ begin
54
+ require 'rcov/rcovtask'
55
+ Rcov::RcovTask.new do |test|
56
+ test.libs << 'test'
57
+ test.pattern = 'test/**/*_test.rb'
58
+ test.verbose = true
59
+ end
60
+ rescue LoadError
61
+ task :rcov do
62
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
63
+ end
64
+ end
65
+
66
+
67
+ task :default => :test
68
+
69
+ require 'rake/rdoctask'
70
+ Rake::RDocTask.new do |rdoc|
71
+ if File.exist?('VERSION.yml')
72
+ config = YAML.load(File.read('VERSION.yml'))
73
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
74
+ else
75
+ version = ""
76
+ end
77
+
78
+ rdoc.rdoc_dir = 'rdoc'
79
+ rdoc.title = "octopi #{version}"
80
+ rdoc.rdoc_files.include('README*')
81
+ rdoc.rdoc_files.include('lib/**/*.rb')
82
+ end
83
+
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 0
4
- :patch: 9
3
+ :minor: 1
4
+ :patch: 0
data/contrib/backup.rb ADDED
@@ -0,0 +1,100 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
2
+
3
+ USAGE_MSG = <<EOF
4
+ Usage: #{$0} <user> [<directory>]
5
+
6
+ Performs a backup of the named user's GitHub.com data.
7
+
8
+ This script will fetch the repositories, along with their metadata and
9
+ associated issues, for the named user. It will also retrieve the user's
10
+ profile, and those of his followers. This data will be stored in
11
+ <directory>/<user>. If a directory is not supplied, ~/.github-backup will be
12
+ used instead.
13
+ EOF
14
+ # TODO: Accept list of targets as argument. The main use case is somebody
15
+ # wanting all of their repositories checked out, without the performane hit
16
+ # and clutter of the extraneous metadata,
17
+ include Octopi
18
+
19
+ class Object
20
+ def to_yaml_file(file)
21
+ File.open("#{file}.yaml", 'w') do |f|
22
+ YAML.dump(self, f)
23
+ end
24
+ end
25
+ end
26
+
27
+ TARGETS = [:user, :followers, :repositories, :issues]
28
+
29
+ @user, @basedir = ARGV
30
+ raise ArgumentError, USAGE_MSG unless @user
31
+ @basedir ||= File.expand_path("~/.github-backup")
32
+ @basedir = File.join(@basedir,@user)
33
+ TARGETS.map{|k| k.to_s}.each do |dir|
34
+ dir = File.join(@basedir,dir)
35
+ FileUtils.mkdir_p(dir) unless File.exists? dir
36
+ end
37
+
38
+ @user = User.find(@user)
39
+
40
+ def user
41
+ puts "* Saving profile"
42
+ @user.to_yaml_file(@user.login)
43
+ end
44
+
45
+ def followers
46
+ @user.followers!.each do |follower|
47
+ puts "* #{follower.login} (#{follower.name})"
48
+ follower.to_yaml_file(follower.login)
49
+ end
50
+ end
51
+
52
+ def repositories
53
+ @user.repositories.each do |repo|
54
+ puts "* #{repo.name} (#{repo.description})\n---"
55
+
56
+ git_dir = File.join(repo.name,'.git')
57
+ # FIXME: Instead of just checking for a Git directory, we could try `git
58
+ # pull`, and if that indicates that the repository doesn't exist, `git
59
+ # clone`
60
+ if File.exists? git_dir
61
+ Dir.chdir repo.name do
62
+ # FIXME: If this fails, try deleting the clone and re-cloning?
63
+ # FIXME: Confirm this is the best solution as opposed to re-cloning
64
+ # every time, using `git fetch` or `git clone --mirror`.
65
+ system("git pull")
66
+ end
67
+ else
68
+ system("git clone #{repo.clone_url}")
69
+ end
70
+ repo.to_yaml_file(repo.name)
71
+ puts
72
+ end
73
+ end
74
+
75
+ # TODO: For forked repositories whose parents have issue trackers, get their
76
+ # issues instead.
77
+ def issues
78
+ FileUtils.mkdir_p @user.repositories.map{|r| r.name}
79
+ @user.repositories.each do |repo|
80
+ puts "#{repo.name}"
81
+ Dir.chdir(repo.name) do
82
+ repo.all_issues.each do |issue|
83
+ puts "* #{issue.title} [#{issue.state}]"
84
+ issue.to_yaml_file(issue.number)
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ TARGETS.each do |target|
91
+ target.to_s.each do |title|
92
+ puts title.capitalize
93
+ title.length.times {print '#'}
94
+ end
95
+ puts
96
+ Dir.chdir(File.join(@basedir, target.to_s)) do
97
+ send(target)
98
+ end
99
+ puts
100
+ end
@@ -0,0 +1,20 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
2
+
3
+ include Octopi
4
+
5
+ authenticated :trace => "curl" do |g|
6
+ repo = g.repository("api-labrat")
7
+
8
+ issue = repo.open_issue :title => "Sample issue",
9
+ :body => "This issue was opened using GitHub API and Octopi"
10
+ puts "Successfully opened issue \##{issue.number}"
11
+
12
+ # # labels = issue.add_label "Working", "Todo"
13
+ # # puts "Labels: #{labels.inspect}"
14
+
15
+ issue.close
16
+ puts "Successfully closed issue \##{issue.number}"
17
+
18
+ # labels = issue.remove_label "Todo"
19
+ # puts "Successfully removed label Todo. Current labels: #{labels.inspect}"
20
+ end
@@ -0,0 +1,14 @@
1
+ #
2
+ # Octopi GitHub API configuration file
3
+ #
4
+
5
+ # GitHub user login and token
6
+ login: github-username
7
+ token: github-token
8
+
9
+ # Trace level
10
+ # Possible values:
11
+ # false - no tracing, same as if the param is ommited
12
+ # true - will output each POST or GET operation to the stdout
13
+ # curl - same as true, but in addition will output the curl equivalent of each command (for debugging)
14
+ trace: curl
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
2
+
3
+ include Octopi
4
+
5
+ user = User.find("fcoury")
6
+ puts user.name
7
+
8
+ repo = user.repository("octopi")
9
+ puts repo.description
10
+
11
+ issue = Issue.find_all(user.login, repo.name).first
12
+ puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
13
+
14
+ issue2 = repo.issues.first
15
+ puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
16
+
17
+ issue3 = repo.issue(issue2.number)
18
+ puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
2
+
3
+ include Octopi
4
+
5
+ # user information
6
+ user = User.find("fcoury")
7
+ puts "#{user.name} is being followed by #{user.followers.join(", ")} and following #{user.following.join(", ")}"
8
+
9
+ # the bang version of followers and following
10
+ # fetches user object for each user, but is
11
+ # a lot more expensive
12
+ user.followers!.each do |u|
13
+ puts " - #{u.name} (#{u.login}) has #{u.public_repo_count} repo(s)"
14
+ end
15
+
16
+ # search user
17
+ users = User.find_all("silva")
18
+ puts "#{users.size} users found for 'silva':"
19
+ users.each do |u|
20
+ puts " - #{u.name}"
21
+ end
22
+
23
+ # repository information
24
+ # to get all repos for user: user.repositories
25
+ repo = user.repository("octopi") # same as: Repository.find("fcoury", "octopi")
26
+ puts "Repository: #{repo.name} - #{repo.description} (by #{repo.owner}) - #{repo.url}"
27
+ puts " Tags: #{repo.tags and repo.tags.map {|t| t.name}.join(", ")}"
28
+
29
+ issue = repo.issues.first
30
+ puts "Sample open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
31
+
32
+ # commits of a the repository
33
+ commit = repo.commits.first
34
+ puts "Commit: #{commit.id} - #{commit.message} - by #{commit.author['name']}"
35
+
36
+ # single commit information
37
+ # details is the same as: Commit.find(commit)
38
+ puts "Diff:"
39
+ commit.details.modified.each {|m| puts "#{m['filename']} DIFF: #{m['diff']}" }
40
+
41
+ # repository search
42
+ repos = Repository.find_all("ruby", "git")
43
+ puts "#{repos.size} repository(ies) with 'ruby' and 'git':"
44
+ repos.each do |r|
45
+ puts " - #{r.name}"
46
+ end
47
+
48
+ # connect "user", "<< token >>" do |github|
49
+ # puts github.user.name
50
+ # end
data/lib/octopi.rb CHANGED
@@ -4,16 +4,13 @@ require 'yaml'
4
4
  require 'pp'
5
5
 
6
6
  module Octopi
7
- class Api; end
8
- ANONYMOUS_API = Api.new
9
-
10
7
  def authenticated(*args, &block)
11
8
  opts = args.last.is_a?(Hash) ? args.last : {}
12
9
  config = read_gitconfig
13
10
  login = config["github"]["user"]
14
11
  token = config["github"]["token"]
15
12
 
16
- api = Api.new(login, token)
13
+ api = AuthApi.new(login, token)
17
14
  api.trace_level = opts[:trace]
18
15
 
19
16
  puts "=> Trace on: #{api.trace_level}" if api.trace_level
@@ -36,7 +33,7 @@ module Octopi
36
33
 
37
34
  puts "=> Trace on: #{trace}" if trace
38
35
 
39
- api = Api.new(login, token)
36
+ api = AuthApi.new(login, token)
40
37
  api.trace_level = trace if trace
41
38
  yield api
42
39
  end
@@ -51,6 +48,7 @@ module Octopi
51
48
  group = $1
52
49
  else
53
50
  key, value = line.split("=")
51
+ value ||= ''
54
52
  (config[group]||={})[key.strip] = value.strip
55
53
  end
56
54
  end
@@ -59,7 +57,6 @@ module Octopi
59
57
  end
60
58
 
61
59
  class Api
62
- include HTTParty
63
60
  CONTENT_TYPE = {
64
61
  'yaml' => 'application/x-yaml',
65
62
  'json' => 'application/json',
@@ -67,9 +64,7 @@ module Octopi
67
64
  }
68
65
  RETRYABLE_STATUS = [403]
69
66
  MAX_RETRIES = 10
70
-
71
- base_uri "http://github.com/api/v2"
72
-
67
+
73
68
  attr_accessor :format, :login, :token, :trace_level, :read_only
74
69
 
75
70
  def initialize(login = nil, token = nil, format = "yaml")
@@ -111,6 +106,11 @@ module Octopi
111
106
  end
112
107
  alias_method :repo, :repository
113
108
 
109
+ def commits(repo,opts={})
110
+ branch = opts[:branch] || "master"
111
+ commits = Commit.find_all(repo, branch, self)
112
+ end
113
+
114
114
  def save(resource_path, data)
115
115
  traslate resource_path, data
116
116
  #still can't figure out on what format values are expected
@@ -140,6 +140,7 @@ module Octopi
140
140
  if @@retries < MAX_RETRIES
141
141
  $stderr.puts e.message
142
142
  @@retries += 1
143
+ sleep 6
143
144
  retry
144
145
  else
145
146
  raise APIError, "GitHub returned status #{e.code}, despite" +
@@ -149,10 +150,23 @@ module Octopi
149
150
  end
150
151
 
151
152
  def post(path, params = {}, format = "yaml")
152
- trace "POST", "/#{format}#{path}", params
153
- submit(path, params, format) do |path, params, format|
154
- resp = self.class.post "/#{format}#{path}", :query => params
155
- resp
153
+ @@retries = 0
154
+ begin
155
+ trace "POST", "/#{format}#{path}", params
156
+ submit(path, params, format) do |path, params, format|
157
+ resp = self.class.post "/#{format}#{path}", :body => params
158
+ resp
159
+ end
160
+ rescue RetryableAPIError => e
161
+ if @@retries < MAX_RETRIES
162
+ $stderr.puts e.message
163
+ @@retries += 1
164
+ sleep 6
165
+ retry
166
+ else
167
+ raise APIError, "GitHub returned status #{e.code}, despite" +
168
+ " repeating the request #{MAX_RETRIES} times. Giving up."
169
+ end
156
170
  end
157
171
  end
158
172
 
@@ -203,8 +217,20 @@ module Octopi
203
217
  puts "#{oper}: #{url}#{par_str}"
204
218
  end
205
219
  end
220
+
221
+ class AuthApi < Api
222
+ include HTTParty
223
+ base_uri "https://github.com/api/v2"
224
+ end
225
+
226
+ class AnonymousApi < Api
227
+ include HTTParty
228
+ base_uri "http://github.com/api/v2"
229
+ end
230
+
231
+ ANONYMOUS_API = AnonymousApi.new
206
232
 
207
233
  %w{error base resource user tag repository issue file_object blob key commit branch}.
208
234
  each{|f| require "#{File.dirname(__FILE__)}/octopi/#{f}"}
209
235
 
210
- end
236
+ end
data/lib/octopi/base.rb CHANGED
@@ -9,7 +9,7 @@ module Octopi
9
9
  :repo => {
10
10
  # FIXME: API currently chokes on repository names containing periods,
11
11
  # but presumably this will be fixed.
12
- :pat => /^[a-z0-9_\.-]+$/,
12
+ :pat => /^[A-Za-z0-9_\.-]+$/,
13
13
  :msg => "%s is an invalid repository name"},
14
14
  :user => {
15
15
  :pat => /^[A-Za-z0-9_\.-]+$/,
@@ -67,20 +67,22 @@ module Octopi
67
67
  def self.extract_user_repository(*args)
68
68
  opts = args.last.is_a?(Hash) ? args.pop : {}
69
69
  if opts.empty?
70
- user, repo = *args if args.length > 1
71
- repo ||= args.first
70
+ if args.length > 1
71
+ repo, user = *args
72
+ else
73
+ repo = args.pop
74
+ end
72
75
  else
73
76
  opts[:repo] = opts[:repository] if opts[:repository]
74
77
  repo = args.pop || opts[:repo]
75
78
  user = opts[:user]
76
79
  end
77
80
 
78
- user ||= repo.owner if repo.is_a? Repository
81
+ user = repo.owner if repo.is_a? Repository
79
82
 
80
83
  if repo.is_a?(String) and !user
81
84
  raise "Need user argument when repository is identified by name"
82
85
  end
83
-
84
86
  ret = extract_names(user, repo)
85
87
  ret << opts
86
88
  ret
data/lib/octopi/branch.rb CHANGED
@@ -5,11 +5,12 @@ module Octopi
5
5
 
6
6
  resource_path "/repos/show/:id"
7
7
 
8
- def self.find(user, repo)
8
+ def self.find(user, repo, api=ANONYMOUS_API)
9
9
  user = user.login if user.is_a? User
10
10
  repo = repo.name if repo.is_a? Repository
11
11
  self.validate_args(user => :user, repo => :repo)
12
- find_plural([user,repo,'branches'], :resource){
12
+ api = ANONYMOUS_API if repo.is_a?(Repository) && !repo.private
13
+ find_plural([user,repo,'branches'], :resource, api){
13
14
  |i| {:name => i.first, :hash => i.last }
14
15
  }
15
16
  end
data/lib/octopi/commit.rb CHANGED
@@ -21,13 +21,14 @@ module Octopi
21
21
  # find_all(:user => "fcoury", :repo => "octopi") # branch defaults to master
22
22
  #
23
23
  def self.find_all(*args)
24
+ api = args.last.is_a?(Api) ? args.pop : ANONYMOUS_API
24
25
  repo = args.first
25
26
  user ||= repo.owner if repo.is_a? Repository
26
27
  user, repo_name, opts = extract_user_repository(*args)
27
28
  self.validate_args(user => :user, repo_name => :repo)
28
29
  branch = opts[:branch] || "master"
29
-
30
- commits = super user, repo_name, branch
30
+ api = ANONYMOUS_API if repo.is_a?(Repository) && !repo.private
31
+ commits = super user, repo_name, branch, api
31
32
  commits.each { |c| c.repository = repo } if repo.is_a? Repository
32
33
  commits
33
34
  end
data/lib/octopi/issue.rb CHANGED
@@ -78,13 +78,17 @@ module Octopi
78
78
  data = @api.post(command_path("edit"), { :title => self.title, :body => self.body })
79
79
  end
80
80
 
81
- %[add remove].each do |oper|
81
+ %w(add remove).each do |oper|
82
82
  define_method("#{oper}_label") do |*labels|
83
83
  labels.each do |label|
84
84
  @api.post("#{prefix("label/#{oper}")}/#{label}/#{number}")
85
85
  end
86
86
  end
87
87
  end
88
+
89
+ def comment(comment)
90
+ @api.post(command_path("comment"), { :comment => comment })
91
+ end
88
92
 
89
93
  private
90
94
  def prefix(command)
@@ -3,27 +3,45 @@ module Octopi
3
3
  include Resource
4
4
  set_resource_name "repository", "repositories"
5
5
 
6
+ create_path "/repos/create"
6
7
  find_path "/repos/search/:query"
7
8
  resource_path "/repos/show/:id"
9
+ delete_path "/repos/delete/:id"
8
10
 
11
+ attr_accessor :private
12
+
13
+ # Returns all branches for the Repository
14
+ #
15
+ # Example:
16
+ # repo = Repository.find("fcoury", "octopi")
17
+ # repo.branches.each { |r| puts r.name }
18
+ #
9
19
  def branches
10
- Branch.find(self.owner, self.name)
20
+ Branch.find(self.owner, self.name,api)
11
21
  end
12
22
 
23
+ # Returns all tags for the Repository
24
+ #
25
+ # Example:
26
+ # repo = Repository.find("fcoury", "octopi")
27
+ # repo.tags.each { |t| puts t.name }
28
+ #
13
29
  def tags
14
30
  Tag.find(self.owner, self.name)
15
31
  end
16
32
 
17
33
  def clone_url
18
- #FIXME: Return "git@github.com:#{self.owner}/#{self.name}.git" if
19
- #user's logged in and owns this repo.
20
- "git://github.com/#{self.owner}/#{self.name}.git"
34
+ if private? || api.login == self.owner
35
+ "git@github.com:#{self.owner}/#{self.name}.git"
36
+ else
37
+ "git://github.com/#{self.owner}/#{self.name}.git"
38
+ end
21
39
  end
22
40
 
23
- def self.find_by_user(user)
41
+ def self.find_by_user(user, api = ANONYMOUS_API)
24
42
  user = user.login if user.is_a? User
25
43
  self.validate_args(user => :user)
26
- find_plural(user, :resource)
44
+ find_plural(user, :resource, api)
27
45
  end
28
46
 
29
47
  def self.find(*args)
@@ -56,7 +74,8 @@ module Octopi
56
74
  end
57
75
 
58
76
  def commits(branch = "master")
59
- Commit.find_all(self, :branch => branch)
77
+ api = self.api || ANONYMOUS_API
78
+ Commit.find_all(self, {:branch => branch}, api)
60
79
  end
61
80
 
62
81
  def issues(state = "open")
@@ -74,6 +93,19 @@ module Octopi
74
93
  def collaborators
75
94
  property('collaborators', [self.owner,self.name].join('/')).values
76
95
  end
96
+
97
+ def self.create(owner, name, opts = {})
98
+ api = owner.is_a?(User) ? owner.api : ANONYMOUS_API
99
+ raise APIError, "To create a repository you must be authenticated." if api.read_only?
100
+ self.validate_args(name => :repo)
101
+ api.post(path_for(:create), opts.merge(:name => name))
102
+ self.find(owner, name, api)
103
+ end
104
+
105
+ def delete
106
+ token = @api.post(self.class.path_for(:delete), :id => self.name)['delete_token']
107
+ @api.post(self.class.path_for(:delete), :id => self.name, :delete_token => token) unless token.nil?
108
+ end
77
109
 
78
110
  end
79
111
  end
@@ -20,6 +20,10 @@ module Octopi
20
20
  @resource_name[key]
21
21
  end
22
22
 
23
+ def create_path(path)
24
+ (@path_spec||={})[:create] = path
25
+ end
26
+
23
27
  def find_path(path)
24
28
  (@path_spec||={})[:find] = path
25
29
  end
@@ -27,6 +31,10 @@ module Octopi
27
31
  def resource_path(path)
28
32
  (@path_spec||={})[:resource] = path
29
33
  end
34
+
35
+ def delete_path(path)
36
+ (@path_spec||={})[:delete] = path
37
+ end
30
38
 
31
39
  def find(*args)
32
40
  api = args.last.is_a?(Api) ? args.pop : ANONYMOUS_API
@@ -42,7 +50,8 @@ module Octopi
42
50
  end
43
51
 
44
52
  def find_all(*s)
45
- find_plural(s, :find)
53
+ api = s.last.is_a?(Api) ? s.pop : ANONYMOUS_API
54
+ find_plural(s, :find, api)
46
55
  end
47
56
 
48
57
  def find_plural(s, path, api = ANONYMOUS_API)
data/lib/octopi/user.rb CHANGED
@@ -4,26 +4,54 @@ module Octopi
4
4
 
5
5
  find_path "/user/search/:query"
6
6
  resource_path "/user/show/:id"
7
-
7
+
8
+ # Finds a single user identified by the given username
9
+ #
10
+ # Example:
11
+ #
12
+ # user = User.find("fcoury")
13
+ # puts user.login # should return 'fcoury'
8
14
  def self.find(username)
9
15
  self.validate_args(username => :user)
10
16
  super username
11
17
  end
12
18
 
19
+ # Finds all users whose username matches a given string
20
+ #
21
+ # Example:
22
+ #
23
+ # User.find_all("oe") # Matches joe, moe and monroe
24
+ #
13
25
  def self.find_all(username)
14
26
  self.validate_args(username => :user)
15
27
  super username
16
28
  end
17
29
 
30
+ # Returns a collection of Repository objects, containing
31
+ # all repositories of the user.
32
+ #
33
+ # If user is the current authenticated user, some
34
+ # additional information will be provided for the
35
+ # Repositories.
18
36
  def repositories
19
- Repository.find_by_user(login)
37
+ api = self.api || ANONYMOUS_API
38
+ Repository.find_by_user(login,api)
20
39
  end
21
40
 
41
+ # Searches for user Repository identified by
42
+ # name
22
43
  def repository(name)
23
44
  self.class.validate_args(name => :repo)
24
45
  Repository.find(login, name)
25
46
  end
26
47
 
48
+ def create_repository(name, opts = {})
49
+ self.class.validate_args(name => :repo)
50
+ Repository.create(self, name, opts)
51
+ end
52
+
53
+ # Adds an SSH Public Key to the user. Requires
54
+ # authentication.
27
55
  def add_key(title, key)
28
56
  raise APIError,
29
57
  "To add a key, you must be authenticated" if @api.read_only?
@@ -35,6 +63,8 @@ module Octopi
35
63
  Key.new(@api, key_params.first, self)
36
64
  end
37
65
 
66
+ # Returns a list of Key objects containing all SSH Public Keys this user
67
+ # currently has. Requires authentication.
38
68
  def keys
39
69
  raise APIError,
40
70
  "To add a key, you must be authenticated" if @api.read_only?
data/octopi.gemspec ADDED
@@ -0,0 +1,67 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{octopi}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Felipe Coury"]
9
+ s.date = %q{2009-07-21}
10
+ s.email = %q{felipe.coury@gmail.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "LICENSE",
18
+ "README.rdoc",
19
+ "Rakefile",
20
+ "VERSION.yml",
21
+ "contrib/backup.rb",
22
+ "examples/authenticated.rb",
23
+ "examples/github.yml.example",
24
+ "examples/issues.rb",
25
+ "examples/overall.rb",
26
+ "lib/octopi.rb",
27
+ "lib/octopi/base.rb",
28
+ "lib/octopi/blob.rb",
29
+ "lib/octopi/branch.rb",
30
+ "lib/octopi/commit.rb",
31
+ "lib/octopi/error.rb",
32
+ "lib/octopi/file_object.rb",
33
+ "lib/octopi/issue.rb",
34
+ "lib/octopi/key.rb",
35
+ "lib/octopi/repository.rb",
36
+ "lib/octopi/resource.rb",
37
+ "lib/octopi/tag.rb",
38
+ "lib/octopi/user.rb",
39
+ "octopi.gemspec",
40
+ "test/octopi_test.rb",
41
+ "test/test_helper.rb"
42
+ ]
43
+ s.has_rdoc = true
44
+ s.homepage = %q{http://github.com/fcoury/octopi}
45
+ s.rdoc_options = ["--charset=UTF-8"]
46
+ s.require_paths = ["lib"]
47
+ s.rubyforge_project = %q{octopi}
48
+ s.rubygems_version = %q{1.3.2}
49
+ s.summary = %q{A Ruby interface to GitHub API v2}
50
+ s.test_files = [
51
+ "test/octopi_test.rb",
52
+ "test/test_helper.rb",
53
+ "examples/authenticated.rb",
54
+ "examples/issues.rb",
55
+ "examples/overall.rb"
56
+ ]
57
+
58
+ if s.respond_to? :specification_version then
59
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
60
+ s.specification_version = 3
61
+
62
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
63
+ else
64
+ end
65
+ else
66
+ end
67
+ end
data/test/octopi_test.rb CHANGED
@@ -7,8 +7,8 @@ class OctopiTest < Test::Unit::TestCase
7
7
 
8
8
  def assert_find_all(cls, check_method, repo, user)
9
9
  repo_method = cls.resource_name(:plural)
10
-
11
- item1 = cls.find_all(user.login, repo.name).first
10
+
11
+ item1 = cls.find_all(repo.name,user.login).first
12
12
  item2 = cls.find_all(repo).first
13
13
  item3 = repo.send(repo_method).first
14
14
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octopi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felipe Coury
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-27 00:00:00 -03:00
12
+ date: 2009-07-21 00:00:00 -03:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -20,11 +20,20 @@ executables: []
20
20
  extensions: []
21
21
 
22
22
  extra_rdoc_files:
23
- - README.rdoc
24
23
  - LICENSE
24
+ - README.rdoc
25
25
  files:
26
+ - .gitignore
27
+ - LICENSE
26
28
  - README.rdoc
29
+ - Rakefile
27
30
  - VERSION.yml
31
+ - contrib/backup.rb
32
+ - examples/authenticated.rb
33
+ - examples/github.yml.example
34
+ - examples/issues.rb
35
+ - examples/overall.rb
36
+ - lib/octopi.rb
28
37
  - lib/octopi/base.rb
29
38
  - lib/octopi/blob.rb
30
39
  - lib/octopi/branch.rb
@@ -37,17 +46,15 @@ files:
37
46
  - lib/octopi/resource.rb
38
47
  - lib/octopi/tag.rb
39
48
  - lib/octopi/user.rb
40
- - lib/octopi.rb
49
+ - octopi.gemspec
41
50
  - test/octopi_test.rb
42
51
  - test/test_helper.rb
43
- - LICENSE
44
52
  has_rdoc: true
45
53
  homepage: http://github.com/fcoury/octopi
46
54
  licenses: []
47
55
 
48
56
  post_install_message:
49
57
  rdoc_options:
50
- - --inline-source
51
58
  - --charset=UTF-8
52
59
  require_paths:
53
60
  - lib
@@ -70,5 +77,9 @@ rubygems_version: 1.3.2
70
77
  signing_key:
71
78
  specification_version: 3
72
79
  summary: A Ruby interface to GitHub API v2
73
- test_files: []
74
-
80
+ test_files:
81
+ - test/octopi_test.rb
82
+ - test/test_helper.rb
83
+ - examples/authenticated.rb
84
+ - examples/issues.rb
85
+ - examples/overall.rb