blastr 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.0.3 2009-01-17
2
+
3
+ * Implementation for both Subversion and Git along with a new structure.
4
+
1
5
  == 0.0.2 2009-01-16
2
6
 
3
7
  * Cleaned up stuff that was specific to the original proof-of-concept.
data/Manifest.txt CHANGED
@@ -5,6 +5,10 @@ README.rdoc
5
5
  Rakefile
6
6
  bin/blastr
7
7
  lib/blastr.rb
8
+ lib/blastr/tts.rb
9
+ lib/blastr/scm.rb
10
+ lib/blastr/git.rb
11
+ lib/blastr/svn.rb
8
12
  script/console
9
13
  script/destroy
10
14
  script/generate
data/README.rdoc CHANGED
@@ -31,8 +31,8 @@ All rights reserved.
31
31
 
32
32
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
33
33
 
34
- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
35
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
36
- * Neither the name of this software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
34
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
35
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
36
+ * Neither the name of this software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
37
37
 
38
38
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/bin/blastr CHANGED
@@ -1,114 +1,40 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- PEOPLE = {
4
- "jdoe" => "John Doe"
5
- }
6
-
7
- class TTSImplementation
8
- attr_accessor :name
9
- def initialize(name)
10
- @name = name
11
- end
12
- def binary
13
- %x[which #{@name}].strip
14
- end
15
- def available?
16
- binary.empty? == false
17
- end
18
- def speak(msg)
19
- %x[#{binary} "#{msg}"]
20
- end
21
- end
22
-
23
- class Say < TTSImplementation
24
- def initialize; super("say"); end
25
- end
26
-
27
- class Espeak < TTSImplementation
28
- def initialize; super("espeak"); end
29
- end
30
-
31
- class Festival < TTSImplementation
32
- def initialize; super("festival"); end
33
- def speak(msg)
34
- %x[echo "#{msg}" | #{binary} --tts]
35
- end
36
- end
37
-
38
- def resolve_tts_system
39
- return $tts unless $tts.nil?
40
- [ Say.new, Espeak.new, Festival.new ].each do |impl|
41
- return impl if impl.available?
42
- end
43
- raise "No TTS implementation found."
44
- end
45
-
46
- def speak(msg)
47
- resolve_tts_system.speak(msg)
48
- end
49
-
50
- def full_name_of(username)
51
- PEOPLE[username] ||= username
52
- end
53
-
54
- class LogEntry
55
- attr_accessor :revision, :author, :comment
56
- def initialize(revision, author, comment)
57
- @revision = revision.to_i
58
- @author = author
59
- @comment = comment
60
- end
61
- def to_s
62
- "revision #{@revision} by #{@author}: #{@comment}"
3
+ require 'rubygems'
4
+ require 'yaml'
5
+ require 'lib/blastr.rb'
6
+ require 'lib/blastr/tts.rb'
7
+
8
+ scm_url = ARGV[0]
9
+ scm = Blastr.scm(scm_url)
10
+ since_revision = scm.as_revision(ARGV[1]) if ARGV.size > 1
11
+ since_revision = scm.latest_revision unless ARGV.size > 1
12
+
13
+ class Author
14
+ PEOPLE_FILE = File.expand_path("~/.blastr/people")
15
+ def self.people
16
+ if File.file?(PEOPLE_FILE)
17
+ yaml = YAML.load_file(PEOPLE_FILE)
18
+ return yaml unless yaml == false
19
+ end
20
+ { }
63
21
  end
64
- end
65
-
66
- def content_of(file)
67
- file = open(file)
68
- content = file.read
69
- file.close
70
- content
71
- end
72
-
73
- def svn_log(working_copy_path, since_revision = 1)
74
- revision = "#{since_revision}:HEAD"
75
- revision = "HEAD" if since_revision == "HEAD"
76
- cmd = "svn log #{working_copy_path} -r #{revision} > /tmp/svn.log"
77
- system(cmd)
78
- content_of("/tmp/svn.log")
79
- end
80
22
 
81
- def svn_log_entries(working_copy_path, since_revision = 1)
82
- entries = []
83
- svn_log(working_copy_path, since_revision).scan(/r(\d+)\s\|\s(.*?)\s\|.*?\n\n(.*)\n-+/).each do |entry|
84
- entries << LogEntry.new(*entry)
23
+ def self.full_name_of(username)
24
+ people[username] ||= username
85
25
  end
86
- entries
87
26
  end
88
27
 
89
- def latest_revision(working_copy_path)
90
- entries = svn_log_entries(working_copy_path, "HEAD")
91
- return entries.first.revision unless entries.empty?
92
- 1
28
+ def announce(commit)
29
+ puts "[#{commit.revision}] Commit by #{commit.author}: #{commit.comment}"
30
+ Blastr::TTS.speak("Commit by #{Author.full_name_of(commit.author)}: #{commit.comment}")
93
31
  end
94
32
 
95
- wc_path = "."
96
- wc_path = ARGV[0] if ARGV.size > 0
97
- revision = latest_revision(wc_path)
98
- revision = ARGV[1].to_i if ARGV.size > 1
99
-
100
- puts "svn path: #{wc_path}\nrevision: #{revision}\n"
101
- speak("Observing Subversion for commits...")
102
-
103
- while true do
104
- svn_log_entries(wc_path, revision).each do |entry|
105
- if entry.revision.to_i > revision
106
- msg = "revision #{entry.revision} by #{full_name_of(entry.author)}: #{entry.comment}"
107
- puts msg
108
- speak(msg)
109
- revision = entry.revision
110
- end
33
+ puts "Polling for #{scm.name} commits since revision #{since_revision}..."
34
+ while true
35
+ scm.commits_since(since_revision.to_s).reverse.each do |commit|
36
+ announce(commit) if since_revision.before?(commit.revision)
37
+ since_revision = commit.revision
111
38
  end
112
- sleep 15
113
- end
114
-
39
+ sleep 30
40
+ end
data/lib/blastr.rb CHANGED
@@ -2,5 +2,28 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  module Blastr
5
- VERSION = '0.0.2'
6
- end
5
+ VERSION = '0.0.3'
6
+
7
+ require 'blastr/git.rb'
8
+ require 'blastr/svn.rb'
9
+
10
+ def Blastr::temp_dir
11
+ temp_file = Tempfile.new("tmp")
12
+ temp_dir = temp_file.path
13
+ temp_file.unlink
14
+ temp_dir
15
+ end
16
+
17
+ def Blastr::scm_implementations
18
+ [ Blastr::Subversion, Blastr::Git ]
19
+ end
20
+
21
+ def Blastr::scm(url)
22
+ scm_implementations.each do |impl|
23
+ if impl.understands_url?(url)
24
+ return impl.new(url)
25
+ end
26
+ end
27
+ raise "No SCM implementation found that would understand #{url}"
28
+ end
29
+ end
data/lib/blastr/git.rb ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'git'
5
+ require 'blastr/scm.rb'
6
+
7
+ module Blastr
8
+
9
+ class GitLogEntry < LogEntry
10
+ def initialize(commit)
11
+ @revision = GitRevision.new(commit.sha)
12
+ @author = commit.author.name
13
+ @comment = commit.message
14
+ end
15
+ end
16
+
17
+ class GitRevision
18
+ attr_accessor :name
19
+
20
+ def initialize(name)
21
+ @name = name
22
+ end
23
+
24
+ def to_s
25
+ @name
26
+ end
27
+
28
+ def before?(revision)
29
+ return false if @name == "HEAD"
30
+ return true if revision.name == "HEAD"
31
+ @name < revision.name
32
+ end
33
+ end
34
+
35
+ class Git
36
+ def name; "Git"; end
37
+
38
+ def self.understands_url?(url)
39
+ url.index("git://") == 0
40
+ end
41
+
42
+ def initialize(git_url)
43
+ @git_url = git_url
44
+ end
45
+
46
+ def as_revision(arg)
47
+ raise "Invalid revision: #{arg}" unless arg =~ /^(HEAD(~\d+)?)|([\d\w:-]+)$/
48
+ GitRevision.new(arg.to_s)
49
+ end
50
+
51
+ def understands_url?(url)
52
+ url.index("git://") == 0
53
+ end
54
+
55
+ def latest_revision
56
+ commits = commits_since(as_revision("HEAD~5"))
57
+ return as_revision("HEAD") unless commits.size > 0
58
+ GitRevision.new(commits.last.revision.to_s)
59
+ end
60
+
61
+ def commits_since(revision)
62
+ @clone = ::Git.clone(@git_url, Blastr::temp_dir)
63
+ begin
64
+ @clone.chdir do
65
+ commits = []
66
+ @clone.log.between(revision.to_s).each do |commit|
67
+ commits << GitLogEntry.new(commit)
68
+ end
69
+ return commits.reverse
70
+ end
71
+ ensure
72
+ FileUtils.remove_dir(@clone.dir, :force => true)
73
+ end
74
+ end
75
+ end
76
+
77
+ end
data/lib/blastr/scm.rb ADDED
@@ -0,0 +1,13 @@
1
+ module Blastr
2
+ class LogEntry
3
+ attr_accessor :revision, :author, :comment
4
+ def initialize(revision, author, comment)
5
+ @revision = revision
6
+ @author = author
7
+ @comment = comment
8
+ end
9
+ def to_s
10
+ "revision #{@revision} by #{@author}: #{@comment}"
11
+ end
12
+ end
13
+ end
data/lib/blastr/svn.rb ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+ require 'blastr/scm.rb'
5
+
6
+ module Blastr
7
+
8
+ class SubversionRevision
9
+ attr_accessor :name
10
+
11
+ def initialize(name)
12
+ @name = name
13
+ end
14
+
15
+ def to_s
16
+ @name
17
+ end
18
+
19
+ def before?(revision)
20
+ return false if @name == "HEAD"
21
+ return true if revision.name == "HEAD"
22
+ @name.to_i < revision.name.to_i
23
+ end
24
+ end
25
+
26
+ class Subversion
27
+ def name; "Subversion"; end
28
+
29
+ def self.understands_url?(url)
30
+ not url.match(/(https?|svn):\/\/.+/).nil?
31
+ end
32
+
33
+ def initialize(svn_url)
34
+ @svn_url = svn_url
35
+ end
36
+
37
+ def as_revision(arg)
38
+ raise "Invalid revision: #{arg}" unless arg =~ /^(HEAD)|(\d+)$/
39
+ SubversionRevision.new(arg.to_s)
40
+ end
41
+
42
+ def latest_revision
43
+ entries = commits_since(as_revision("HEAD"))
44
+ return entries.first.revision unless entries.empty?
45
+ 1
46
+ end
47
+
48
+ def commits_since(since_revision = 1)
49
+ entries = []
50
+ svn_log(since_revision).scan(/r(\d+)\s\|\s(.*?)\s\|.*?\n\n(.*)\n-+/).each do |entry|
51
+ revision = as_revision(entry[0])
52
+ author = entry[1]
53
+ comment = entry[2]
54
+ entries << LogEntry.new(revision, author, comment)
55
+ end
56
+ entries.reverse
57
+ end
58
+
59
+ private
60
+ def svn_log(since_revision = as_revision("1"))
61
+ temp_file = Tempfile.new("svn.log").path
62
+ begin
63
+ revision = "#{since_revision}:#{as_revision('HEAD')}"
64
+ revision = as_revision("HEAD") if since_revision.to_s == as_revision("HEAD").to_s
65
+ cmd = "svn log #{@svn_url} -r #{revision} > #{temp_file}"
66
+ system(cmd)
67
+ return content_of(temp_file)
68
+ ensure
69
+ FileUtils.remove_file(temp_file)
70
+ end
71
+ end
72
+
73
+ private
74
+ def content_of(file)
75
+ file = open(file)
76
+ content = file.read
77
+ file.close
78
+ content
79
+ end
80
+
81
+ end
82
+
83
+ end
data/lib/blastr/tts.rb ADDED
@@ -0,0 +1,52 @@
1
+ module Blastr
2
+ module TTS
3
+
4
+ class TTSImplementation
5
+ attr_accessor :name
6
+
7
+ def initialize(name)
8
+ @name = name
9
+ end
10
+
11
+ def binary
12
+ %x[which #{@name}].strip
13
+ end
14
+
15
+ def available?
16
+ binary.empty? == false
17
+ end
18
+
19
+ def speak(msg)
20
+ %x[#{binary} "#{msg}"]
21
+ end
22
+ end
23
+
24
+ class Say < TTSImplementation
25
+ def initialize; super("say"); end
26
+ end
27
+
28
+ class Espeak < TTSImplementation
29
+ def initialize; super("espeak"); end
30
+ end
31
+
32
+ class Festival < TTSImplementation
33
+ def initialize; super("festival"); end
34
+ def speak(msg)
35
+ %x[echo "#{msg}" | #{binary} --tts]
36
+ end
37
+ end
38
+
39
+ def TTS::resolve_tts_system
40
+ return $tts unless $tts.nil?
41
+ [ Say.new, Espeak.new, Festival.new ].each do |impl|
42
+ return impl if impl.available?
43
+ end
44
+ raise "No TTS implementation found."
45
+ end
46
+
47
+ def TTS::speak(msg)
48
+ resolve_tts_system.speak(msg)
49
+ end
50
+
51
+ end
52
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blastr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lasse Koskela
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-16 00:00:00 +02:00
12
+ date: 2009-01-17 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -52,6 +52,10 @@ files:
52
52
  - Rakefile
53
53
  - bin/blastr
54
54
  - lib/blastr.rb
55
+ - lib/blastr/tts.rb
56
+ - lib/blastr/scm.rb
57
+ - lib/blastr/git.rb
58
+ - lib/blastr/svn.rb
55
59
  - script/console
56
60
  - script/destroy
57
61
  - script/generate