Skip to content
This repository was archived by the owner on Dec 13, 2023. It is now read-only.

Commit 96e67d1

Browse files
committed
[NEW] Adding Bazaar support: Add commits.rb and head.rb adapter modules with unit tests.
Michael
1 parent da7229b commit 96e67d1

File tree

5 files changed

+176
-0
lines changed

5 files changed

+176
-0
lines changed

lib/scm/adapters/bzr/commits.rb

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
module Scm::Adapters
2+
class BzrAdapter < AbstractAdapter
3+
4+
# Return the number of commits in the repository following +since+.
5+
def commit_count(since=0)
6+
commit_tokens(since || 0).size
7+
end
8+
9+
# Return the list of commit tokens following +since+.
10+
def commit_tokens(since=0)
11+
tokens = run("#{rev_list_command(since)} --log-format=line | cut -d':' -f1").split("\n")
12+
end
13+
14+
# Returns a list of shallow commits (i.e., the diffs are not populated).
15+
# Not including the diffs is meant to be a memory savings when
16+
# we encounter massive repositories. If you need all commits
17+
# including diffs, you should use the each_commit() iterator,
18+
# which only holds one commit in memory at a time.
19+
def commits(since=0)
20+
log = run("#{rev_list_command(since)} | cat")
21+
a = Scm::Parsers::BzrParser.parse(log)
22+
end
23+
24+
# Returns a single commit, including its diffs
25+
def verbose_commit(token)
26+
log = run("cd '#{self.url}' && bzr log -v -c #{token}")
27+
Scm::Parsers::BzrParser.parse(log).first
28+
end
29+
30+
# Yields each commit after +since+, including its diffs.
31+
# The log is stored in a temporary file.
32+
# This is designed to prevent excessive RAM usage when we
33+
# encounter a massive repository. Only a single commit is ever
34+
# held in memory at once.
35+
def each_commit(since=0)
36+
open_log_file(since) do |io|
37+
Scm::Parsers::BzrParser.parse(io) do |commit|
38+
yield commit if block_given? && commit.token != since
39+
end
40+
end
41+
end
42+
43+
# Not used by Ohloh proper, but handy for debugging and testing
44+
def log(since=0)
45+
run "#{rev_list_command(since)} -v"
46+
end
47+
48+
# Returns a file handle to the log.
49+
# In our standard, the log should include everything AFTER
50+
# +since+. However, bzr doesn't work that way; it returns
51+
# everything after and INCLUDING +since+. Therefore, consumers
52+
# of this file should check for and reject the duplicate commit.
53+
def open_log_file(since=0)
54+
begin
55+
if since == head_token # There are no new commits
56+
# As a time optimization, just create an empty
57+
# file rather than fetch a log we know will be empty.
58+
File.open(log_filename, 'w') { }
59+
else
60+
run "#{rev_list_command} -v > #{log_filename}"
61+
end
62+
File.open(log_filename, 'r') { |io| yield io }
63+
ensure
64+
File.delete(log_filename) if FileTest.exist?(log_filename)
65+
end
66+
end
67+
68+
def log_filename
69+
File.join('/tmp', (self.url).gsub(/\W/,'') + '.log')
70+
end
71+
72+
def rev_list_command(since=nil)
73+
"cd '#{self.url}' && bzr log --forward -r #{since ? since+1 : 1}.."
74+
end
75+
end
76+
end

lib/scm/adapters/bzr/head.rb

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module Scm::Adapters
2+
class BzrAdapter < AbstractAdapter
3+
def head_token
4+
run("bzr revno -q #{url}").strip
5+
end
6+
7+
def head
8+
verbose_commit(head_token)
9+
end
10+
11+
def parent_tokens(commit)
12+
run("cd '#{url}' && bzr log -c $((#{commit.token} - 1)) --log-format=line | cut -f1 -d':'").split("\n")
13+
end
14+
15+
def parents(commit)
16+
parent_tokens(commit).collect { |token| verbose_commit(token) }
17+
end
18+
end
19+
end

lib/scm/adapters/bzr_adapter.rb

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ def english_name
77
end
88

99
require 'lib/scm/adapters/bzr/validation'
10+
require 'lib/scm/adapters/bzr/commits'
11+
require 'lib/scm/adapters/bzr/head'

test/unit/bzr_commits_test.rb

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
require File.dirname(__FILE__) + '/../test_helper'
2+
3+
module Scm::Adapters
4+
class BzrCommitsTest < Scm::Test
5+
6+
def test_commit_count
7+
with_bzr_repository('bzr') do |bzr|
8+
assert_equal 6, bzr.commit_count
9+
assert_equal 6, bzr.commit_count(0)
10+
assert_equal 5, bzr.commit_count(1)
11+
assert_equal 1, bzr.commit_count(5)
12+
assert_equal 0, bzr.commit_count(6)
13+
end
14+
end
15+
16+
def test_commit_tokens
17+
with_bzr_repository('bzr') do |bzr|
18+
assert_equal ['1', '2', '3', '4', '5', '6'], bzr.commit_tokens
19+
assert_equal ['2', '3', '4', '5', '6'], bzr.commit_tokens(1)
20+
assert_equal ['6'], bzr.commit_tokens(5)
21+
assert_equal [], bzr.commit_tokens(6)
22+
end
23+
end
24+
25+
def test_commits
26+
with_bzr_repository('bzr') do |bzr|
27+
assert_equal ['1', '2', '3', '4', '5', '6'], bzr.commits.collect { |c| c.token }
28+
assert_equal ['6'], bzr.commits(5).collect { |c| c.token }
29+
assert_equal [], bzr.commits(6).collect { |c| c.token }
30+
31+
# Check that the diffs are not populated
32+
assert_equal [], bzr.commits.first.diffs
33+
end
34+
end
35+
36+
def test_each_commit
37+
with_bzr_repository('bzr') do |bzr|
38+
commits = []
39+
bzr.each_commit do |c|
40+
assert c.committer_name
41+
assert c.committer_date.is_a?(Time)
42+
assert c.message.length > 0
43+
assert c.diffs.any?
44+
# Check that the diffs are populated
45+
c.diffs.each do |d|
46+
assert d.action =~ /^[MAD]$/
47+
assert d.path.length > 0
48+
end
49+
commits << c
50+
end
51+
52+
# Make sure we cleaned up after ourselves
53+
assert !FileTest.exist?(bzr.log_filename)
54+
55+
# Verify that we got the commits in forward chronological order
56+
assert_equal ['1', '2', '3', '4', '5', '6'], commits.collect{ |c| c.token }
57+
end
58+
end
59+
end
60+
end
61+

test/unit/bzr_head_test.rb

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require File.dirname(__FILE__) + '/../test_helper'
2+
3+
module Scm::Adapters
4+
class BzrHeadTest < Scm::Test
5+
6+
def test_head_and_parents
7+
with_bzr_repository('bzr') do |bzr|
8+
assert_equal '6', bzr.head_token
9+
assert_equal '6', bzr.head.token
10+
assert bzr.head.diffs.any? # diffs should be populated
11+
12+
assert_equal '5', bzr.parents(bzr.head).first.token
13+
assert bzr.parents(bzr.head).first.diffs.any?
14+
end
15+
end
16+
17+
end
18+
end

0 commit comments

Comments
 (0)