grudge 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.txt ADDED
@@ -0,0 +1,2 @@
1
+ == 0.1.0 / 2008-10-22
2
+ * First of many versions
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Justin Knowlden
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,108 @@
1
+ # Grudge
2
+
3
+ Grudge is a stand-alone system, which means you run it on your own, that watches the comments of some git repository and provides a web interface to allow people to rate the comments.
4
+
5
+ ## Why would someone want to do this?
6
+
7
+ In my experience, code commit comments have been very funny; or at least very good reads. It's kind of an insight into some of the programmer's minds. At one point, I was scouring the commit comments and sending a daily email of the ones I thought were funny. The emails were well received, so I figured there must be something to this.
8
+
9
+ Thus, the goals are:
10
+
11
+ 1. Make people laugh
12
+ 2. Inform others - besides those in development - of the day-to-day
13
+
14
+ I also hope that something like this will make for better commit comments; since you know you are now being watched ... and judged.
15
+
16
+ ## Why is it called Grudge?
17
+
18
+ Well, basically I typed 'rate' into Apple's thesaurus app and noticed the word 'judge'. I wanted to add a 'G' to the front of the app - since this is a git commit watcher - and so hit upon 'grudge'.
19
+
20
+ Alas, Grudge = Git Judge
21
+
22
+ ## How does it work?
23
+
24
+ Once your system is bootstrapped, grudge will monitor for updates. For each commit, grudge will store the SHA hash of the commit-id (for referential reasons) and the date it was committed (for ordering reasons). Commit messages and other commit data (like author) stay in the git repository and are always retrieved from there; even at a possible speed reduction (though grudge seems pretty quick).
25
+
26
+ Each vote is recorded for a commit as either a +1 or a -1. Votes are themselves entities, which means you could get the voting history for any commit.
27
+
28
+ Commits have a net score, which is simply the sum of all of the votes. Popular commits are those with the highest net score. Unpopular are those with the lowest net score.
29
+
30
+ # Using Grudge
31
+
32
+ ## Requirements
33
+
34
+ * [Sinatra](http://github.com/bmizerany/sinatra/tree/master)
35
+ * [Ruby Git](http://github.com/schacon/ruby-git/tree/master)
36
+ * [HAML](http://haml.hamptoncatlin.com/)
37
+ * [Sqlite3-ruby](http://github.com/jamis/sqlite3-ruby/tree/master)
38
+
39
+ * DataMapper - `sudo gem install data_mapper`
40
+ * DataObjects - `sudo gem install data_objects` ... *if not already installed*
41
+ * DataObject bindings for Sqlite - `sudo gem install do_sqlite3`
42
+ * JSON Pure - `sudo gem install json_pure` - annoyingly needed by data_mapper
43
+
44
+ ## Setting up an app
45
+
46
+ ### Install the gem
47
+
48
+ $ sudo gem install thumblemonks-grudge
49
+
50
+ ### Setup an instance
51
+
52
+ $ mkdir foo && cd foo
53
+ $ grudge init
54
+
55
+ ### Tell Grudge about your repository
56
+
57
+ Edit the file in your Grudge instance called `config/grudge.yml`. In it edit the git repository url that you want Grudge to watch. For now, do this for both development and production entries. You don't need to edit anything else, unless you just can't help yourself.
58
+
59
+ Example:
60
+
61
+ ...
62
+ repository:
63
+ url: git://github.com/thumblemonks/grudge.git
64
+ ...
65
+
66
+ ### Run the app
67
+
68
+ When just playing around, you can run:
69
+
70
+ $ grudge start
71
+
72
+ This will first clone the remote repository you defined, bootstrap the commits in a local Sqlite database, then run the Sinatra web-app. As long as you don't remove `clone.git`, the cloning will only happen on the first run. Grudge will, however, grab new updates from the repo each time you start it.
73
+
74
+ Point your browser at `http://localhost:9292/` and you are done.
75
+
76
+ Oh yeah ... advertise it!
77
+
78
+ #### Phusion
79
+
80
+ It is suggested that you run grudge through Apache via [Phusion Passenger](http://www.modrails.com/). In order to do this, simply point a configured Phusion Virtual Host at the `public` directory wherever you ran `grudge init`.
81
+
82
+ ### Getting automatic updates
83
+
84
+ As of this writing the way to tell Grudge to automatically look for updates is to setup a remote repository via a post-receive hook. This means your instance of Grudge will need to be routable by your git server.
85
+
86
+ If this is so, just setup a post-receive hook to hit the URL with a POST request:
87
+
88
+ http(s)://your-grudge-instance/repository/pull
89
+
90
+ #### Manual updates
91
+
92
+ You can update manually by either restarting the app or via the Grudge console like so:
93
+
94
+ $ grudge pull
95
+
96
+ You could also setup a bash alias like the following:
97
+
98
+ wget -q --post-data='\'''\'' --no-cookies --delete-after http://your-grudge-instance/repository/pull
99
+
100
+ Not that I did that ;)
101
+
102
+ # Acknowledgements
103
+
104
+ Someone for sure. I guess my [wife](http://lesfeministes.com) for giving me the Saturday to write this.
105
+
106
+ # Legal
107
+
108
+ Copyright © 2008 Justin Knowlden, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'lib/boot'
5
+
6
+ desc 'Default task: run all tests'
7
+ task :default => [:test]
8
+
9
+ desc 'Run all tests'
10
+ Rake::TestTask.new do |t|
11
+ t.test_files = FileList['test/*_test.rb']
12
+ t.verbose = true
13
+ end
14
+
15
+ desc "Open an irb session preloaded with this library"
16
+ task :console do
17
+ sh "irb -rubygems -r ./lib/boot.rb"
18
+ end
data/TODO.markdown ADDED
@@ -0,0 +1,27 @@
1
+ # Todo
2
+
3
+ ## 0.1.0
4
+
5
+ * Get it started
6
+ * Make it a gem
7
+ * Command line options
8
+ * Make grudge start in production mode as a policy ;)
9
+
10
+ ## Backlog
11
+
12
+ * Effective logging - not sure if logging git transactions is enough
13
+ * Paging: so we can see more commits
14
+ * Only allow one vote per person (maybe, honesty is often the best policy)
15
+ * [Dan Hodos](http://github.com/danhodos) proved to me that honesty just sucks
16
+ * Allow users to add tags
17
+ * Show results by tag
18
+ * Allow users to comment on commits
19
+ * Allow users to filter commits based on whether they were commented-on/rated
20
+ * RSS feeds
21
+ * Especially for tags
22
+ * UJS
23
+ * Ask for local/remote git repo URI on command line and pre-bootstrap
24
+ * Might name Suck to Boring
25
+ * Sparkline of voting history
26
+ * Handle branches
27
+ * Move away from DataMapper unless it gets better support?
data/bin/grudge ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+ Signal.trap("INT") { puts "Exiting grudge"; exit } # If we need it
5
+
6
+ def usage
7
+ $stderr.puts "Usage: grudge [init|start|pull]"
8
+ end
9
+
10
+ def fire_up
11
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'boot')
12
+ Grudge::Config.fire_me_up(:production)
13
+ Grudge::Database.fire_me_up
14
+ Grudge::Repository.open_or_clone
15
+ end
16
+
17
+ def mkdir(dir)
18
+ if File.exists?(dir)
19
+ puts "- Existing directory #{dir} untouched"
20
+ else
21
+ puts "- Creating directory #{dir}"
22
+ FileUtils.mkdir(dir)
23
+ end
24
+ end
25
+
26
+ def cp_grudge_file(src, dest)
27
+ unless File.exists?(dest)
28
+ puts "- Copying grudge file #{src} to #{dest}"
29
+ FileUtils.cp(File.join(File.dirname(__FILE__), src), dest)
30
+ else
31
+ puts "- Existing file #{dest} untouched"
32
+ end
33
+ end
34
+
35
+ if ARGV.length == 1
36
+ case ARGV.shift
37
+ when 'start'
38
+ puts "Starting grudge ... but, why not just use Phusion with Rack?"
39
+ app = File.join(File.dirname(__FILE__), '..', 'lib', 'grudge.rb')
40
+ %x[rackup config.ru]
41
+ when 'pull'
42
+ puts "Pulling latest commits"
43
+ fire_up
44
+ Commit.download!
45
+ when 'init'
46
+ puts "Initializing grudge instance"
47
+ %w[public tmp config].each { |dir| mkdir("./#{dir}") }
48
+ cp_grudge_file('../config/grudge.yml', './config/grudge.yml')
49
+ cp_grudge_file('../config.ru', './config.ru')
50
+ else
51
+ usage
52
+ end
53
+ else
54
+ usage
55
+ end
data/config.ru ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+ require 'sinatra'
4
+
5
+ Sinatra::Application.default_options.update(
6
+ :run => false,
7
+ :env => :production,
8
+ :raise_errors => true
9
+ )
10
+
11
+ require 'grudge'
12
+
13
+ run Sinatra.application
data/config/grudge.yml ADDED
@@ -0,0 +1,31 @@
1
+ #
2
+ # Database entries feed directly into DataMapper.setup
3
+ #
4
+ production:
5
+ log: 'grudge.log'
6
+ database:
7
+ adapter: 'sqlite3'
8
+ database: 'grudge.db'
9
+ repo:
10
+ master: 'clone.git'
11
+ #
12
+ # Hey you! You should change only this setting
13
+ origin: 'git://example.com/repository.git'
14
+
15
+ #
16
+ # You don't need to change anything below here
17
+ test:
18
+ log: '/dev/null'
19
+ database: 'sqlite3::memory:'
20
+ repo:
21
+ master: 'test/clone.git'
22
+ origin: 'test/origin.git'
23
+
24
+ development:
25
+ log: 'grudge_development.log'
26
+ database:
27
+ adapter: 'sqlite3'
28
+ database: 'grudge_development.db'
29
+ repo:
30
+ master: 'clone.git'
31
+ origin: 'git://example.com/repository.git'
data/grudge.gemspec ADDED
@@ -0,0 +1,64 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "grudge"
3
+ s.version = "0.1.0"
4
+ s.date = "2008-10-22"
5
+ s.summary = "Grudge is a git commit comment judging web-app"
6
+ s.email = "gus@gusg.us"
7
+ s.homepage = "http://github.com/thumblemonks/grudge"
8
+ s.description = "Grudge is a stand-alone system, which means you run it on your own, that watches the comments of some git repository and provides a web interface to allow people to rate the comments."
9
+ s.authors = ["Justin Knowlden"]
10
+
11
+ s.bindir = "bin"
12
+ s.executables = ["grudge"]
13
+ s.default_executable = "grudge"
14
+
15
+ s.has_rdoc = true
16
+ s.rdoc_options = ["--main", "README.markdown"]
17
+ s.extra_rdoc_files = ["HISTORY.txt", "README.markdown"]
18
+
19
+ s.add_dependency("sinatra", [">= 0.3.1"])
20
+ s.add_dependency("git", [">= 1.0.5"])
21
+ s.add_dependency("haml", [">= 2.0.3"])
22
+ s.add_dependency("sqlite3-ruby", [">= 1.2.4"])
23
+ s.add_dependency("data_mapper", [">= 0.9.7"])
24
+ s.add_dependency("data_objects", [">= 0.9.7"])
25
+ s.add_dependency("do_sqlite3", [">= 0.9.7"])
26
+ s.add_dependency("json_pure", [">= 1.1.3"]) # datamapper! grrr
27
+
28
+ # run git ls-files to get an updated list
29
+ s.files = %w[
30
+ HISTORY.txt
31
+ MIT-LICENSE
32
+ README.markdown
33
+ Rakefile
34
+ TODO.markdown
35
+ bin/grudge
36
+ config.ru
37
+ config/grudge.yml
38
+ grudge.gemspec
39
+ lib/boot.rb
40
+ lib/grudge.rb
41
+ lib/grudge/base.rb
42
+ lib/grudge/config.rb
43
+ lib/grudge/database.rb
44
+ lib/grudge/extensions.rb
45
+ lib/grudge/helpers.rb
46
+ lib/grudge/repository.rb
47
+ lib/models/commit.rb
48
+ lib/models/vote.rb
49
+ lib/views/application.haml
50
+ lib/views/application.sass
51
+ lib/views/index.haml
52
+ lib/views/not_found.haml
53
+ lib/views/show.haml
54
+ ]
55
+ s.test_files = %w[
56
+ test/commit_test.rb
57
+ test/config_test.rb
58
+ test/grudge_test.rb
59
+ test/model_factory.rb
60
+ test/repository_test.rb
61
+ test/test_helper.rb
62
+ test/vote_test.rb
63
+ ]
64
+ end
data/lib/boot.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+
3
+ # TODO: Move to Kernel or something
4
+ def require_local_lib(pattern)
5
+ Dir.glob(File.join(File.dirname(__FILE__), pattern)).each {|f| require f }
6
+ end
7
+ require_local_lib('grudge/*.rb')
8
+ require_local_lib('models/*.rb')
data/lib/grudge.rb ADDED
@@ -0,0 +1,73 @@
1
+ require File.join(File.dirname(__FILE__), 'boot')
2
+ require 'sinatra'
3
+
4
+ # Configuration
5
+
6
+ configure(:development, :test) { require 'ruby-debug' }
7
+
8
+ configure do
9
+ set_option :views, File.join(File.dirname(__FILE__), 'views')
10
+ set_option :public, File.join(File.dirname(__FILE__), 'public')
11
+ Grudge::Config.fire_me_up(Sinatra.env)
12
+ Grudge::Database.fire_me_up
13
+ end
14
+
15
+ configure :development, :production do
16
+ Grudge::Repository.open_or_clone
17
+ Commit.download!
18
+ end
19
+
20
+ # Setup
21
+
22
+ include Grudge::Sinatra::Extensions
23
+
24
+ catch_all_css
25
+ template(:layout) {:application}
26
+ not_found {haml :not_found}
27
+
28
+ helpers do
29
+ include Grudge::Sinatra::Helpers
30
+ end
31
+
32
+ # Top-level actions
33
+
34
+ get("/") { redirect '/recent' }
35
+
36
+ %w[recent popular unpopular].each do |scope|
37
+ get "/#{scope}" do
38
+ set_title("#{scope.to_s.capitalize} commits")
39
+ @commits = Commit.send(scope)
40
+ haml :index
41
+ end
42
+ end
43
+
44
+ %w[awesome suck].each do |vote|
45
+ get "/:sha/#{vote}" do
46
+ commit = Commit.first(:sha => params[:sha])
47
+ raise Sinatra::NotFound unless commit
48
+ commit.send("#{vote}!")
49
+ redirect "/#{commit.sha}"
50
+ end
51
+ end
52
+
53
+ get '/:sha' do
54
+ show_commit(Commit.first(:sha => params[:sha]))
55
+ end
56
+
57
+ # TODO: search across all sorts of fields; not just commit id
58
+ post '/search' do
59
+ show_commit(Commit.search(params['query'].to_s))
60
+ end
61
+
62
+ post '/repository/pull' do
63
+ Commit.download!
64
+ end
65
+
66
+ private
67
+
68
+ def show_commit(commit)
69
+ raise Sinatra::NotFound unless commit
70
+ @commit = commit
71
+ set_title(commit.sha)
72
+ haml :show
73
+ end
@@ -0,0 +1,16 @@
1
+ module Grudge
2
+ VERSION = '0.1.0'
3
+ module Hash
4
+ def symbolize_keys
5
+ self.mash { |k,v| {k.to_sym => v} }
6
+ end
7
+ end
8
+ end # Grudge
9
+
10
+ module Enumerable
11
+ def mash
12
+ self.inject({}) { |a,i| a.merge( yield(i) ) }
13
+ end
14
+ end # Enumerable
15
+
16
+ Hash.send(:include, Grudge::Hash)