ginst 0.0.0 → 0.1.2

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 (48) hide show
  1. data/CHANGELOG +3 -0
  2. data/Manifest +35 -0
  3. data/README.txt +1 -0
  4. data/Rakefile +17 -54
  5. data/bin/ginst +12 -0
  6. data/bin/ginst_master +11 -0
  7. data/ginst.gemspec +47 -0
  8. data/lib/app/authorization.rb +44 -0
  9. data/lib/app/views/assets/jquery.corners.js +7 -0
  10. data/lib/app/views/assets/jquery.js +19 -0
  11. data/lib/app/views/branch_index.haml +4 -0
  12. data/lib/app/views/clean_layout.haml +17 -0
  13. data/lib/app/views/commit.haml +8 -0
  14. data/lib/app/views/commits.haml +8 -0
  15. data/lib/app/views/full_commit.haml +38 -0
  16. data/lib/app/views/index.haml +1 -0
  17. data/lib/app/views/layout.haml +32 -0
  18. data/lib/app/views/not_found.haml +3 -0
  19. data/lib/app/views/project.haml +1 -0
  20. data/lib/app/views/project_index.haml +11 -0
  21. data/lib/app/views/style.sass +107 -0
  22. data/lib/app/webserver.rb +113 -0
  23. data/lib/ginst/command_line.rb +45 -0
  24. data/lib/ginst/ginst.rb +73 -0
  25. data/lib/ginst/master_command_line.rb +40 -0
  26. data/lib/ginst/plugin.rb +16 -0
  27. data/lib/ginst/project.rb +40 -0
  28. data/lib/ginst/server.rb +51 -0
  29. data/lib/ginst/templates/rgithook.rb +6 -0
  30. data/lib/ginst.rb +12 -0
  31. data/test/app/test_webserver.rb +21 -0
  32. data/test/test_ginst.rb +84 -0
  33. data/test/test_helper.rb +36 -0
  34. data/test/test_project.rb +8 -0
  35. data/test/test_server.rb +75 -0
  36. data.tar.gz.sig +4 -0
  37. metadata +131 -35
  38. metadata.gz.sig +0 -0
  39. data/.document +0 -5
  40. data/.gitignore +0 -21
  41. data/LICENSE +0 -20
  42. data/README.rdoc +0 -18
  43. data/features/ginst.feature +0 -9
  44. data/features/step_definitions/ginst_steps.rb +0 -0
  45. data/features/support/env.rb +0 -4
  46. data/spec/ginst_spec.rb +0 -7
  47. data/spec/spec.opts +0 -1
  48. data/spec/spec_helper.rb +0 -9
@@ -0,0 +1,107 @@
1
+ body
2
+ margin: 0
3
+ padding: 0
4
+ #container
5
+ width: 80%
6
+ margin: 0 auto
7
+ #header
8
+ padding: 0 10px
9
+ margin-bottom: 48px
10
+ #logo
11
+ width: 150px
12
+ text-align: center
13
+ margin-bottom: 20px
14
+ h1
15
+ width: 150px
16
+ text-align: center
17
+ margin: 0
18
+ padding: 10px 0px 0px 0px
19
+ font-family: Futura, Verdana, Arial, Helvetica, sans-serif
20
+ font-size: 32px
21
+ h2
22
+ width: 150px
23
+ text-align: center
24
+ font-family: Arial, Helvetica, sans-serif
25
+ font-size: 12px
26
+ padding-bottom: 0px
27
+ margin-top: 0px
28
+ #left
29
+ float: left
30
+ width: 12em
31
+ padding: 0
32
+ overflow: hidden
33
+ ul
34
+ margin: 0px 0px 24px 5px
35
+ padding: 0px
36
+ list-style-type: none
37
+ font-family: Verdana, Geneva, sans-serif
38
+ text-transform: uppercase
39
+ line-height: 24px
40
+ a
41
+ text-decoration: none
42
+ color: black
43
+ ul
44
+ margin: 0px 0px 24px 25px
45
+ padding: 0px
46
+ list-style-type: none
47
+ font-family: Verdana, Geneva, sans-serif
48
+ text-transform: lowercase
49
+ line-height: 18px
50
+ #mainContent
51
+ margin: 0 20px 0 13em
52
+ .separator
53
+ margin: 0px 0px 6px 0px
54
+ padding: 3px
55
+ line-height: 24px
56
+ list-style-type: none
57
+ font-family: Arial, Helvetica, sans-serif
58
+ list-style-type: none
59
+ border-bottom: 1px dotted #666
60
+ padding-bottom: 0px
61
+ margin-bottom: 12px
62
+ font-weight: bolder
63
+ .success
64
+ background: #7CC979
65
+ .notest
66
+ background: #CCCC66
67
+ .fail
68
+ background: #BF6A6A
69
+ .commit
70
+ margin: 0px 0px 6px 0px
71
+ padding: 3px
72
+ line-height: 24px
73
+ list-style-type: none
74
+ height: 48px
75
+ font-family: Arial, Helvetica, sans-serif
76
+ overflow: hidden
77
+ img
78
+ float: left
79
+ width: 42px
80
+ margin: 3px
81
+ .sha1, .message, .author, .time
82
+ margin: 0px 3px 0px 3px
83
+ .sha1
84
+ float: left
85
+ .message
86
+ margin-left: 120px
87
+ font-weight: bolder
88
+ .author a
89
+ text-decoration: none
90
+ color: #333
91
+ .author
92
+ float: left
93
+ .time
94
+ text-align: right
95
+ color: #333
96
+ #footer
97
+ font-family: Arial, Helvetica, sans-serif
98
+ clear: both
99
+ padding: 0 10px
100
+ background: #DDDDDD
101
+ p
102
+ margin: 0 auto
103
+ text-align: center
104
+ padding: 10px 0
105
+ .version
106
+ font-size: smaller
107
+
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'sinatra'
4
+ require 'optparse'
5
+ require 'ruby-debug'
6
+ require 'digest/md5'
7
+ require File.join(File.dirname(__FILE__),'authorization')
8
+
9
+ begin
10
+ require 'ginst'
11
+ require 'ginst/plugin'
12
+ rescue LoadError
13
+ require File.join(File.dirname(__FILE__),'..','ginst')
14
+ end
15
+
16
+
17
+ set :views, File.dirname(__FILE__) + '/views'
18
+ set :public, File.dirname(__FILE__) + '/views/assets'
19
+
20
+ helpers do
21
+ def format_message(text)
22
+ text.gsub!("\t",'  ')
23
+ text.gsub!("\n",'<br/>')
24
+ text
25
+ end
26
+
27
+ def redirect_back
28
+ redirect request.referer
29
+ end
30
+ end
31
+
32
+ def load_ginst
33
+ @ginst = Ginst::Ginst.new(ENV["REPO_PATH"] || Dir.pwd)
34
+ #@ginst.add_project '~/Documents/ginst'
35
+ end
36
+
37
+ def load_project
38
+ load_ginst
39
+ @project = @ginst[params[:project] || @ginst.projects.first ] or raise Sinatra::NotFound
40
+ end
41
+
42
+ def load_branch
43
+ load_project
44
+ @branch = @project.branch(params[:branch] || 'master')
45
+ @per_page = (params[:per_page] && params[:per_page].to_i) || 30
46
+ @page = (params[:page] && params[:page].to_i) || 0
47
+ @commits = @project.repo.commits(@branch.commit.id,@per_page, @page*@per_page)
48
+ end
49
+
50
+ def load_commit
51
+ load_project
52
+ @commit = @project.repo.commit(params[:commit])
53
+ end
54
+
55
+
56
+ get '/' do
57
+ load_ginst
58
+ redirect @ginst.projects.first.name
59
+ load_ginst
60
+ haml :index
61
+ end
62
+
63
+ get '/:project' do
64
+ load_project
65
+ haml :project_index
66
+ end
67
+
68
+ post '/:project' do
69
+ load_project
70
+ @project.install_ginst
71
+ redirect_back
72
+ end
73
+
74
+ get '/:project/branch/:branch' do
75
+ load_branch
76
+ haml :branch_index
77
+ end
78
+
79
+ get '/:project/commit/:commit' do
80
+ load_commit
81
+ haml :full_commit
82
+ end
83
+
84
+ post '/:project/commit/:commit' do
85
+ load_commit
86
+ @project.run_hooks_for_commit(@commit)
87
+ redirect_back
88
+ end
89
+
90
+ not_found do
91
+ haml :not_found, :layout => :clean_layout
92
+ end
93
+
94
+ error do
95
+ 'Sorry there was a nasty error - ' + env['sinatra.error'].name
96
+ end
97
+
98
+ error Exception do
99
+ 'Sorry there was a nasty error - ' + env['sinatra.error'].name
100
+ end
101
+
102
+ get '/about' do
103
+ "I'm running on Version " + Sinatra::VERSION
104
+ end
105
+
106
+ get '/style.css' do
107
+ content_type 'text/css', :charset => 'utf-8'
108
+ # css_files = Dir.glob(File.join(File.dirname(File.expand_path(__FILE__)),'views','assets','*.css'))
109
+ # css_files.map{|f| File.read f}.join("\n")
110
+ sass :style
111
+ end
112
+
113
+
@@ -0,0 +1,45 @@
1
+ require 'optparse'
2
+ require 'grit'
3
+ module Ginst
4
+ class CommandLine
5
+ def self.run
6
+ options = parse()
7
+ puts %x(#{$0} --help) unless options[:command]
8
+ exit(0) if options[:command] == :exit || !options[:command]
9
+
10
+ if [:start,:stop,:restart,:status].include? options[:command]
11
+ Server.send(options[:command],options)
12
+ Process.waitall
13
+ Server.status(options) unless options[:command] == :status
14
+ end
15
+
16
+ Ginst.install(options) if options[:command] == :install
17
+
18
+ rescue OptionParser::InvalidOption, OptionParser::AmbiguousOption
19
+ puts "Invalid options #{ARGV}"
20
+ puts %x(#{$0} --help)
21
+ rescue Grit::InvalidGitRepositoryError
22
+ puts "Invalid path #{options[:path]}. Not found a git repo"
23
+ end
24
+
25
+ def self.parse
26
+ options = {}
27
+ OptionParser.new do |opts|
28
+ opts.banner = "Usage: #{File.basename($0)} [options]"
29
+
30
+ opts.on_head('-s','--start','Start the web server') { options[:command] = :start }
31
+ opts.on_head('-t','--stop', 'Stop the web server') { options[:command] = :stop }
32
+ opts.on_head('-r','--restart','Restart the web server') { options[:command] = :restart }
33
+ opts.on_head('-a','--status', 'Show status of the web server') { options[:command] = :status }
34
+ opts.on_head('-p','--port PORT','Webserver port') {|p| options[:port] = p.to_i }
35
+ opts.on_head('-i','--install [PATH]', 'Install ginst') {|p| options[:command] = :install ; p and options[:path] = p }
36
+ opts.on('-p', '--path GIT_WORK_DIR', 'Specify other path (default current dir)'){|p| options[:path] = p}
37
+ opts.on_tail("-h", "--help", 'Show help') { options[:command]=:exit; puts opts }
38
+ opts.on_tail("-v", "--version", 'Show version') { options[:command]=:exit; puts "Ginst version #{Ginst::Version}" }
39
+ end.parse!
40
+
41
+ options[:path] ||= Dir.pwd
42
+ options
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,73 @@
1
+ require 'fileutils'
2
+ require 'rgithook'
3
+ require 'ginst/project'
4
+
5
+ module Ginst
6
+ class Ginst
7
+
8
+ attr_reader :projects
9
+ def initialize(path = nil)
10
+ @projects = [Project.new(path || Dir.pwd)]
11
+ end
12
+
13
+ def [](project_name)
14
+ @projects.select{|p| p.name == project_name}.first
15
+ end
16
+
17
+ def add_project(path_or_project)
18
+ case path_or_project
19
+ when String
20
+ @projects << Project.new(path_or_project)
21
+ when Project
22
+ @projects << path_or_project
23
+ end
24
+ end
25
+ # Install Ginst in the given path
26
+ # Options can be:
27
+ # * :verbose: true/false
28
+ def self.install(path,options={})
29
+ self.new(path).install(options)
30
+ end
31
+
32
+ def install(options = {})
33
+ opts={:verbose => true, :interactive => true}
34
+ opts.merge(options)
35
+
36
+ puts 'Installing rgithook' if opts[:verbose]
37
+ @rgithook = RGitHook::RGitHook.new(@path)
38
+ @rgithook.install(opts[:interactive])
39
+
40
+ #check for a valid repo
41
+ @path = Grit::Repo.new(@path).path
42
+ @ginst_dir = File.join(@path,'ginst')
43
+
44
+ puts 'Installing ginst' if opts[:verbose]
45
+ install_ginst(opts)
46
+
47
+ puts 'Installing hooks' if opts[:verbose]
48
+ install_hook(opts)
49
+ end
50
+
51
+ def self.install_master(path,options)
52
+ self.new(path).install_mater(options)
53
+ end
54
+
55
+ private
56
+
57
+ def install_ginst(opts)
58
+ puts "Installing Ginst in #{@path}" if opts[:verbose]
59
+ FileUtils.mkdir(@ginst_dir) unless File.directory? @ginst_dir
60
+ FileUtils.cp_r(template_path,@ginst_dir, {:preserve => true, :verbose => opts[:verbose]})
61
+ end
62
+
63
+ def install_hook(opts)
64
+ puts
65
+ @rgithook.conf_file
66
+ end
67
+
68
+
69
+ def template_path
70
+ File.join(File.dirname(__FILE__),'..','app','.')
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,40 @@
1
+ require 'optparse'
2
+ require 'ruby-debug'
3
+ module Ginst
4
+ class CommandLine
5
+ def self.run
6
+ options = parse()
7
+ puts %x(#{$0} --help) unless options[:command]
8
+ exit(0) if options[:command] == :exit || !options[:command]
9
+
10
+ if [:start,:stop,:restart,:status].include? options[:command]
11
+ Server.send(options[:command])
12
+ Process.waitall
13
+ Server.status unless options[:command] == :status
14
+ end
15
+
16
+ rescue OptionParser::InvalidOption, OptionParser::AmbiguousOption
17
+ puts "Invalid options #{ARGV}"
18
+ puts %x(#{$0} --help)
19
+ end
20
+
21
+ def self.parse
22
+ options = {}
23
+ OptionParser.new do |opts|
24
+ opts.banner = "Usage: #{File.basename($0)} [options]"
25
+
26
+ opts.on_head('-s','--start','Start the web server') { options[:command] = :start }
27
+ opts.on_head('-t','--stop', 'Stop the web server') { options[:command] = :stop }
28
+ opts.on_head('-r','--restart','Restart the web server') { options[:command] = :restart }
29
+ opts.on_head('-a','--status', 'Show status of the web server') { options[:command] = :status }
30
+ opts.on_head('-i','--install [PATH]', 'Install ginst') {|p| options[:command] = :install ; p and options[:path] = p }
31
+ opts.on('-p', '--path GIT_WORK_DIR', 'Specify other path (default current dir)'){|p| options[:path] = p}
32
+ opts.on_tail("-h", "--help", 'Show help') { options[:command]=:exit; puts opts }
33
+ opts.on_tail("-v", "--version", 'Show version') { options[:command]=:exit; puts "Ginst version #{Ginst::Version}" }
34
+ end.parse!
35
+
36
+ options[:path] ||= Dir.pwd
37
+ options
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+
2
+ module Ginst
3
+ class GinstPlugin < ::RGitHook::Plugin
4
+
5
+ module RunnerMethods
6
+ def ginst_post_receive(old_commit,new_commit,ref)
7
+ repo.commits_between(old_commit,new_commit).each do |commit|
8
+ test(commit)
9
+ end
10
+
11
+ %x(say 'hello')
12
+ repo.commit(old_commit).properties[:gritted] = "YES"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module Ginst
3
+ class Project
4
+ include RGitHook
5
+ attr_reader :path, :rgithook, :repo, :name
6
+ def initialize(path)
7
+ @path = path
8
+ @rgithook = RGitHook.new(path)
9
+ @repo = @rgithook.repo
10
+ @name = @rgithook.project_name
11
+ end
12
+
13
+ def branches
14
+ @repo.branches
15
+ end
16
+
17
+ def branch(branch_name)
18
+ @repo.branches.select{|b| b.name == branch_name}.first
19
+ end
20
+
21
+ def commits(branch_name)
22
+ @repo.commits(branch(branch_name).sha)
23
+ end
24
+
25
+ def install_ginst
26
+ @rgithook.install(false)
27
+ File.open(@rgithook.hooks_file,'w') do |f|
28
+ f.write File.read(File.join(File.dirname(__FILE__),'templates','rgithook.rb'))
29
+ f.close
30
+ end
31
+ @rgithook = RGitHook.new(@path)
32
+ end
33
+
34
+ def run_hooks_for_commit(commit)
35
+ @rgithook.post_receive(commit.parents.first.sha,commit.sha,'any')
36
+ end
37
+ end
38
+ end
39
+
40
+
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'daemons'
3
+
4
+ module Ginst
5
+ class Server
6
+ DEFAULT_PORT = 7654
7
+
8
+ # Options are:
9
+ # :port => Web server port
10
+ # :path => Repo path
11
+ def self.start(options = {})
12
+ puts "Starting ginst for #{options[:path]} at http://localhost:#{options[:port] || DEFAULT_PORT}"
13
+ fork{run_daemon_with_env(options[:path],['start','--',sinatra_options(options)])}
14
+ end
15
+
16
+ def self.stop(options = {})
17
+ fork{run_daemon_with_env(options[:path],['stop'])}
18
+ end
19
+
20
+ def self.restart(options = {})
21
+ puts "Restarting ginst for #{options[:path]} at http://localhost:#{options[:port] || DEFAULT_PORT}"
22
+ run_daemon_with_env(options[:path],['restart','--',sinatra_options(options)])
23
+ end
24
+
25
+ def self.status(options = {})
26
+ run_daemon_with_env(options[:path],['status']).show_status.to_s
27
+ end
28
+
29
+ private
30
+
31
+ def self.run_daemon_with_env(path,env)
32
+ rgithook = ::RGitHook::RGitHook.new(path)
33
+ daemons_options = {:app_name => "ginst-#{rgithook.project_name}", :dir_mode=>:normal, :dir=>rgithook.path, :ARGV => env, :multiple => false, :log_output => true, :monitor => true, :mode => :exec}
34
+ ENV['REPO_PATH'] = path
35
+ Daemons.run(server_path(path),daemons_options)
36
+ end
37
+
38
+ def self.sinatra_options(options)
39
+ sinatra_options = "-p #{options.delete(:port) || DEFAULT_PORT} -e production"
40
+ end
41
+
42
+ # Try to load de server of the local repo .git/ginst/webserver
43
+ # but if it does not exists, load the default
44
+ def self.server_path(path)
45
+ local_file = File.join(Grit::Repo.new(path).path,'ginst','webserver.rb')
46
+ system_file= File.expand_path(File.join(File.dirname(__FILE__),'..','app','webserver.rb'))
47
+ File.file?(local_file) ? local_file : system_file
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,6 @@
1
+ require 'ginst'
2
+ require 'ginst/plugin'
3
+
4
+ on :post_receive, :background => true do |old_commit,new_commit,ref|
5
+ ginst_post_receive(old_commit,new_commit,ref)
6
+ end
data/lib/ginst.rb CHANGED
@@ -0,0 +1,12 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ module Ginst
4
+ VERSION = '0.1.1'
5
+ end
6
+
7
+ require 'rubygems'
8
+ require 'rgithook'
9
+
10
+ Ginst.autoload(:Ginst, 'ginst/ginst')
11
+ Ginst.autoload(:Server, 'ginst/server')
12
+ Ginst.autoload(:CommandLine, 'ginst/command_line')
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'sinatra/test/unit'
4
+ require File.dirname(__FILE__) + '/../../lib/app/webserver'
5
+
6
+ class SinatraServer < Test::Unit::TestCase
7
+ def test_index
8
+ mock_ginst
9
+ get '/'
10
+ end
11
+ def test_project_index
12
+ mock_ginst
13
+ get '/test_project'
14
+ end
15
+
16
+ def test_branch_index
17
+ mock_ginst
18
+ get '/test_project/master'
19
+ end
20
+
21
+ end
@@ -0,0 +1,84 @@
1
+ require 'test_helper'
2
+
3
+ class TestGinst < Test::Unit::TestCase
4
+ include Ginst
5
+
6
+ def test_new
7
+ assert_instance_of Ginst, Ginst.new
8
+
9
+ end
10
+
11
+ def test_find_project
12
+ mock_repo
13
+ Ginst.new
14
+ end
15
+ end
16
+
17
+ # attr_reader :projects
18
+ # def initialize(path = nil)
19
+ # @projects = [Project.new(path || Dir.pwd)]
20
+ # end
21
+ #
22
+ # def [](project_name)
23
+ # @projects.select{|p| p.name == project_name}.first
24
+ # end
25
+ #
26
+ # def add_project(path_or_project)
27
+ # case path_or_project
28
+ # when String
29
+ # @projects << Project.new(path_or_project)
30
+ # when Project
31
+ # @projects << path_or_project
32
+ # end
33
+ # end
34
+ # # Install Ginst in the given path
35
+ # # Options can be:
36
+ # # * :verbose: true/false
37
+ # def self.install(path,options={})
38
+ # self.new(path).install(options)
39
+ # end
40
+ #
41
+ # def install(options = {})
42
+ # opts={:verbose => true, :interactive => true}
43
+ # opts.merge(options)
44
+ #
45
+ # puts 'Installing rgithook' if opts[:verbose]
46
+ # @rgithook = RGitHook::RGitHook.new(@path)
47
+ # @rgithook.install(opts[:interactive])
48
+ #
49
+ # #check for a valid repo
50
+ # @path = Grit::Repo.new(@path).path
51
+ # @ginst_dir = File.join(@path,'ginst')
52
+ #
53
+ # puts 'Installing ginst' if opts[:verbose]
54
+ # install_ginst(opts)
55
+ #
56
+ # puts 'Installing hooks' if opts[:verbose]
57
+ # install_hook(opts)
58
+ # end
59
+ #
60
+ # def self.install_master(path,options)
61
+ # self.new(path).install_mater(options)
62
+ # end
63
+ #
64
+ # private
65
+ #
66
+ # def install_ginst(opts)
67
+ # puts "Installing Ginst in #{@path}" if opts[:verbose]
68
+ # FileUtils.mkdir(@ginst_dir) unless File.directory? @ginst_dir
69
+ # FileUtils.cp_r(template_path,@ginst_dir, {:preserve => true, :verbose => opts[:verbose]})
70
+ # end
71
+ #
72
+ # def install_hook(opts)
73
+ # puts
74
+ # @rgithook.conf_file
75
+ # end
76
+ #
77
+ #
78
+ # def template_path
79
+ # File.join(File.dirname(__FILE__),'..','app','.')
80
+ # end
81
+ # end
82
+ # end
83
+ #
84
+ #
@@ -0,0 +1,36 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/ginst'
3
+ require 'rubygems'
4
+ require 'grit'
5
+ require 'mocha'
6
+
7
+ def mock_repo
8
+ repo = mock('Grit::Repo')
9
+ repo.stubs(:'is_a?').with(::Grit::Repo).returns(true)
10
+ repo.stubs(:path).with().returns('path')
11
+ repo.stubs(:bare).with().returns('false')
12
+
13
+ branch = mock('Grit::Branch')
14
+ branch.stubs(:name).with().returns('master')
15
+
16
+ repo.stubs(:branches).with().returns([branch])
17
+ Grit::Repo.stubs(:new).returns(repo)
18
+
19
+ repo
20
+ end
21
+
22
+ def mock_ginst
23
+ repo = mock_repo
24
+
25
+ ginst = mock('Ginst::Ginst')
26
+ ginst.stubs(:add_project)
27
+
28
+ project = mock('Ginst::Project')
29
+ project.stubs(:name).returns('test_project')
30
+ project.stubs(:branches).returns(repo.branches)
31
+ project.stubs(:branch).with('master').returns([])
32
+
33
+ ginst.stubs(:[]).returns(project)
34
+ ginst.stubs(:projects).returns([project])
35
+ Ginst::Ginst.stubs(:new).returns(ginst)
36
+ end
@@ -0,0 +1,8 @@
1
+
2
+
3
+ class TestProject < Test::Unit::TestCase
4
+
5
+
6
+ def test_something
7
+ end
8
+ end