hookers 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,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 hookers.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ - Provides hooks to integrate with Pivotal Tracker
2
+ - Generates changelogs descriptions based on standard commit messages and tagging
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ Historias e bugs:
2
+
3
+ * FEATURE #29418015: - http://pivotaltracker.com/story/show/29418015
4
+ - [FINISHED #29418015] adicionado - http://github.com/rhruiz/hookers/commit/d08f16b
5
+ - [FINISHED #29418015] adicionado - http://github.com/rhruiz/hookers/commit/d346159
6
+ - [FINISHED #29418015] Teste - http://github.com/rhruiz/hookers/commit/d3cbcd5
7
+
8
+ * FEATURE #29349419: - http://pivotaltracker.com/story/show/29349419
9
+ - [finished #29349419] corrigindo a sintaxe no post-commit - http://github.com/rhruiz/hookers/commit/8359b38
10
+ - [finished #29349419] alterando o post-commit file - http://github.com/rhruiz/hookers/commit/e0dca8b
11
+ - [STORY #29349419] alterando o post-commit file - http://github.com/rhruiz/hookers/commit/a79f429
12
+ - [STORY #29349419] adicionando commands - http://github.com/rhruiz/hookers/commit/2ad28c7
13
+ - [STORY #29349419] resolvendo conflitos do merge - http://github.com/rhruiz/hookers/commit/6a557f8
14
+ - [STORY #29349419] alterando a permissão de execução para o hook - http://github.com/rhruiz/hookers/commit/de33617
15
+ - [STORY #29349419] adicionando permissão de execução para o hook - http://github.com/rhruiz/hookers/commit/8218b57
16
+ - [STORY #29349419] criando o método de setup dos hooks do git - http://github.com/rhruiz/hookers/commit/38cf24a
17
+
18
+ * FEATURE #29348711: - http://pivotaltracker.com/story/show/29348711
19
+ - [STORY #29348711] Initial changelog commands - http://github.com/rhruiz/hookers/commit/4e71c06
data/bin/hookers ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'hookers'
5
+
6
+ args = ARGV.dup
7
+ command = args.shift
8
+
9
+ Hookers.run!(command, args)
data/hookers.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "hookers/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "hookers"
7
+ s.version = Hookers::VERSION
8
+ s.authors = ["Ricardo Hermida Ruiz"]
9
+ s.email = ["rhruiz@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = "Git hooks and change logs"
12
+ s.description = "Contains default hooks files to integrate git with pivotal tracker and change log generator"
13
+
14
+ s.rubyforge_project = "hookers"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency "slop", "~> 2.1"
22
+
23
+ s.add_runtime_dependency "rest-client"
24
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Changelog
5
+ class Affects
6
+ attr_accessor :commit, :type, :number
7
+
8
+ def bug?
9
+ self.type == "BUG"
10
+ end
11
+
12
+ def feature?
13
+ self.type == "FEATURE"
14
+ end
15
+
16
+ def type=(value)
17
+ @type = (value == "BUG" ? "BUG" : "FEATURE")
18
+ end
19
+
20
+ def identifier
21
+ "#{type} ##{number}"
22
+ end
23
+
24
+ def uri
25
+ return "http://bugzilla-qa.linux.locaweb.com.br/show_bug.cgi?id=#{self.number}" if bug?
26
+ return "http://pivotaltracker.com/story/show/#{self.number}" if feature?
27
+ end
28
+
29
+ def initialize(commit, type, number)
30
+ self.commit = commit
31
+ self.type = type
32
+ self.number = number
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'stringio'
4
+
5
+ module Hookers
6
+ module Changelog
7
+ class Changelogger
8
+ def initialize(project = Project.discover)
9
+ @project = project
10
+ end
11
+
12
+ def generate(options = {})
13
+ from = options[:from] || History.first
14
+ to = options[:to] || "HEAD"
15
+ lines = History.between(from, to)
16
+ parser = Parser.new(@project)
17
+ commits = lines.map { |e| parser.parse(e) }.flatten.group_by(&:identifier)
18
+
19
+ output = StringIO.new
20
+
21
+ output.puts "Historias e bugs:"
22
+ commits.each_pair do |identifier, commits|
23
+ output.puts "\n * #{identifier}: - #{commits.first.uri}"
24
+ commits.each do |affected|
25
+ output.puts " - #{affected.commit.message} - #{affected.commit.uri}"
26
+ end
27
+ end
28
+
29
+ output.rewind
30
+ output.read
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Changelog
5
+ class Commit
6
+ attr_accessor :id, :message, :project
7
+
8
+ def initialize(project, id, message)
9
+ self.project = project
10
+ self.id = id
11
+ self.message = message
12
+ end
13
+
14
+ def uri
15
+ project.commit_uri(self.id)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Changelog
5
+ class History
6
+ def self.first
7
+ %x[git rev-list --all --reverse | head -1].strip
8
+ end
9
+
10
+ def self.between(from, to)
11
+ lines = %x[git log --oneline #{from}..#{to}].split(/\n/)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Changelog
5
+ class Parser
6
+ attr_accessor :project, :message
7
+
8
+ REGEXP = /\[(bug|feature|story|fixed|fixes|completed|finished|delivers)\s+\#\s*(\d+)\]/i
9
+
10
+ def initialize(project)
11
+ self.project = project
12
+ end
13
+
14
+ def parse(line)
15
+ id, message = line.split(" ", 2)
16
+ data = message.scan(Parser::REGEXP)
17
+ affects = []
18
+ commit = Commit.new(project, id, message)
19
+
20
+ if !data.nil?
21
+ data.each do |type, number|
22
+ affects << Affects.new(commit, type.upcase, number)
23
+ end
24
+ end
25
+
26
+ affects
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Changelog
5
+ class Project
6
+ attr_accessor :name, :uri
7
+
8
+ def initialize(name, uri)
9
+ self.name = name
10
+ self.uri = uri
11
+ end
12
+
13
+ def commit_uri(id)
14
+ "#{self.uri}/commit/#{id}"
15
+ end
16
+
17
+ def self.discover
18
+ remote_uri = %x[git remote -v].split(/\n/).first.split(/\s+/).at(1)
19
+
20
+ return nil if remote_uri.nil?
21
+ remote_uri.gsub!(/(git@|git:\/\/)/, "http://")
22
+ remote_uri.gsub!(/:(?!\/\/)/, "/")
23
+ remote_uri.gsub!(/\.git$/, "")
24
+ name = remote_uri.split(/\//).at(-1)
25
+ new(name, remote_uri)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ require "hookers/changelog/project"
2
+ require "hookers/changelog/affects"
3
+ require "hookers/changelog/changelogger"
4
+ require "hookers/changelog/commit"
5
+ require "hookers/changelog/history"
6
+ require "hookers/changelog/parser"
7
+ require "hookers/commands/changelog"
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ def self.commands
5
+ @@commands ||= {}
6
+ end
7
+
8
+ module Command
9
+ def self.included(base)
10
+ Hookers.commands[base.name.gsub(/^Hookers::Commands::/, "").downcase] = base
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Commands
5
+ class Changelog
6
+ include Hookers::Command
7
+
8
+ def self.slop
9
+ Slop.new(help: true, banner: "Generates changelogs based on commit messages") do
10
+ on :from, "Generate changelog from this refence", argument: true
11
+ on :to, "Generate changelog up to this reference", argument: true
12
+ on :setup, "Copy git hooks files to project .git/hooks ", argument: true
13
+ end
14
+ end
15
+
16
+ attr_accessor :options
17
+
18
+ def initialize(command, args)
19
+ self.class.slop.parse(args)
20
+ self.options = self.class.slop.to_hash
21
+ end
22
+
23
+ def run
24
+ puts Hookers::Changelog::Changelogger.new.generate(options)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Commands
5
+ class GitCommit
6
+ include Hookers::Command
7
+
8
+ attr_accessor :options, :command, :git
9
+
10
+ KEYS = %w(bug feature story fixed fixes completed finished delivers)
11
+
12
+ KEYS.each{|command| Hookers.commands[command] = self }
13
+
14
+ def self.slop
15
+ Slop.new(help: true) do
16
+ on :m, "Message to be used on commit", argument: true
17
+ on :id, "Pivotal story id", argument: true
18
+ end
19
+ end
20
+
21
+ def initialize(command, args)
22
+ self.class.slop.parse(args)
23
+ self.options = self.class.slop.to_hash
24
+ self.git = Git::Repository.new
25
+ end
26
+
27
+ def run
28
+ puts git.commit "[#{self.command.upcase} ##{options[:id]}] #{options[:m]}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Commands
5
+ class GitSetup
6
+ include Hookers::Command
7
+
8
+ attr_accessor :options
9
+
10
+ Hookers.commands["setup"] = self
11
+
12
+ def initialize(command, args)
13
+ self.class.slop.parse(args)
14
+ self.options = self.class.slop.to_hash
15
+ end
16
+
17
+ def run
18
+ puts Hookers::Git.setup
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Commands
5
+ class Help
6
+ include Hookers::Command
7
+
8
+ attr_accessor :args
9
+
10
+ def initialize(command, args)
11
+ self.args = args
12
+ end
13
+
14
+ def run
15
+ if args.length == 0 || Hookers.commands[args[0]] == nil
16
+ puts "Use hookers help <command> for additional options\nAvailable commands: "
17
+ Hookers.commands.keys.each { |k| puts "\t#{k}" }
18
+ return
19
+ end
20
+
21
+ if Hookers.commands[args[0]] && Hookers.commands[args[0]].respond_to?(:slop)
22
+ puts Hookers.commands[args[0]].slop.help
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Commands
5
+ class Pivotal
6
+ include Hookers::Command
7
+
8
+ attr_accessor :options
9
+
10
+ def self.slop
11
+ Slop.new(help: true) do
12
+ on :"api-token", "Pivotal user token to sync commits", argument: true
13
+ end
14
+ end
15
+
16
+ def initialize(command, args)
17
+ self.class.slop.parse(args)
18
+ self.options = self.class.slop.to_hash
19
+ end
20
+
21
+ def run
22
+ puts Hookers::Pivotal::TrackerProject.new(options[:"api-token"]).notify_changes
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ require "cgi"
2
+
3
+ module Hookers
4
+ module Git
5
+ class Commit
6
+ attr_accessor :id, :author, :message
7
+
8
+ def initialize(id, author, message)
9
+ self.id = id
10
+ self.author = author
11
+ self.message = message
12
+ end
13
+
14
+ def to_xml
15
+ "<source_commit>
16
+ <commit_id> #{ self.id } </commit_id>
17
+ <author> #{ CGI::escapeHTML(self.author) } </author>
18
+ <message> #{ CGI::escapeHTML(self.message) } </message>
19
+ </source_commit>"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ require 'shellwords'
2
+
3
+ module Hookers
4
+ module Git
5
+ class Repository
6
+ def last_commit
7
+ revision = %x(git log -1 HEAD --format=%H%n%an%n%s).split("\n")
8
+ Git::Commit.new(revision[0], revision[1], revision[2])
9
+ end
10
+
11
+ def commit(message)
12
+ %x(git commit -m'#{message}')
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+ require 'fileutils'
3
+
4
+ module Hookers
5
+ module Git
6
+ extend self
7
+
8
+ def root_path
9
+ path = Dir.pwd
10
+
11
+ while (path != "/") and ! Dir.entries(path).include?(".git") do
12
+ path = File.expand_path("..", path)
13
+ end
14
+ path
15
+ end
16
+
17
+ def setup
18
+ from_path = "#{Hookers.root}/scripts/git/post-commit"
19
+ to_path = "#{root_path}/.git/hooks/post-commit"
20
+
21
+ FileUtils.cp(from_path, to_path)
22
+ FileUtils.chmod 0755, to_path
23
+
24
+ "setup successfully"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ module Hookers
5
+ module Pivotal
6
+ module HttpClient
7
+ extend self
8
+
9
+ def post(url, body, headers)
10
+ uri = URI.parse(url)
11
+ http = Net::HTTP.new(uri.host)
12
+ request = Net::HTTP::Post.new(uri.request_uri)
13
+
14
+ request.body = body
15
+ request.initialize_http_header headers
16
+
17
+ http.request(request)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+
3
+ module Hookers
4
+ module Pivotal
5
+ class TrackerProject
6
+ attr_accessor :token, :base_uri, :git
7
+
8
+ def initialize(token)
9
+ raise "Pivotal api token not found" unless token
10
+ self.token = token
11
+ self.git = Git::Repository.new
12
+ self.base_uri = 'http://www.pivotaltracker.com/'
13
+ end
14
+
15
+ def commit_uri
16
+ "#{self.base_uri}services/v3/source_commits"
17
+ end
18
+
19
+ def notify_changes
20
+ puts "Notifying pivotal tracker of changes..."
21
+
22
+ commit = git.last_commit
23
+
24
+ response = HttpClient.post(commit_uri, commit.to_xml, { "X-TrackerToken" => self.token, "Content-type" => "application/xml" })
25
+
26
+ puts "Pivotal notified succesfully" if response.code == "200"
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ require "hookers/git/commit"
2
+ require "hookers/git/repository"
3
+ require "hookers/git/setup"
4
+ require "hookers/pivotal/http_client"
5
+ require "hookers/pivotal/tracker_project"
6
+ require "hookers/commands/pivotal"
7
+ require "hookers/commands/git_setup"
8
+ require "hookers/commands/git_commit"
@@ -0,0 +1,3 @@
1
+ module Hookers
2
+ VERSION = "0.1.0"
3
+ end
data/lib/hookers.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "hookers/version"
2
+ require "hookers/command"
3
+ require "hookers/commands/help"
4
+
5
+ require "hookers/changelog"
6
+ require "hookers/pivotal"
7
+
8
+ require "slop"
9
+
10
+ module Hookers
11
+ extend self
12
+
13
+ def root
14
+ File.expand_path '../..', __FILE__
15
+ end
16
+
17
+ def self.run!(command, options = {})
18
+ commands.fetch(command, Hookers::Commands::Help).new(command, options).run
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+
2
+ if [ "$PIVOTAL_TRACKER_TOKEN" = "" ]; then
3
+ echo "set PIVOTAL_TRACKER_TOKEN in the environment to enable notification";
4
+ exit 1;
5
+ else
6
+ hookers pivotal --api-token=$PIVOTAL_TRACKER_TOKEN;
7
+ exit $?;
8
+ fi
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hookers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ricardo Hermida Ruiz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-11 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: slop
16
+ requirement: &70208915722140 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70208915722140
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ requirement: &70208915721720 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70208915721720
36
+ description: Contains default hooks files to integrate git with pivotal tracker and
37
+ change log generator
38
+ email:
39
+ - rhruiz@gmail.com
40
+ executables:
41
+ - CHANGELOG.md
42
+ - hookers
43
+ extensions: []
44
+ extra_rdoc_files: []
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - README.md
49
+ - Rakefile
50
+ - bin/CHANGELOG.md
51
+ - bin/hookers
52
+ - hookers.gemspec
53
+ - lib/hookers.rb
54
+ - lib/hookers/changelog.rb
55
+ - lib/hookers/changelog/affects.rb
56
+ - lib/hookers/changelog/changelogger.rb
57
+ - lib/hookers/changelog/commit.rb
58
+ - lib/hookers/changelog/history.rb
59
+ - lib/hookers/changelog/parser.rb
60
+ - lib/hookers/changelog/project.rb
61
+ - lib/hookers/command.rb
62
+ - lib/hookers/commands/changelog.rb
63
+ - lib/hookers/commands/git_commit.rb
64
+ - lib/hookers/commands/git_setup.rb
65
+ - lib/hookers/commands/help.rb
66
+ - lib/hookers/commands/pivotal.rb
67
+ - lib/hookers/git/commit.rb
68
+ - lib/hookers/git/repository.rb
69
+ - lib/hookers/git/setup.rb
70
+ - lib/hookers/pivotal.rb
71
+ - lib/hookers/pivotal/http_client.rb
72
+ - lib/hookers/pivotal/tracker_project.rb
73
+ - lib/hookers/version.rb
74
+ - scripts/git/post-commit
75
+ homepage: ''
76
+ licenses: []
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project: hookers
95
+ rubygems_version: 1.8.10
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: Git hooks and change logs
99
+ test_files: []