Skip to content
This repository was archived by the owner on Feb 7, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ gem 'httparty'

gem 'bullet'
gem 'pry-rails'

gem 'rugged', git: 'git://github.com/libgit2/rugged.git', branch: 'development', submodules: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under the circumstances, this seems like the version to use. They just aren't making numbered releases with any frequency.

gem 'colorize'

group :assets do
Expand Down
9 changes: 9 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
GIT
remote: git://github.com/libgit2/rugged.git
revision: 5f0f3fad0e8af98a10812673e8316b78e5075437
branch: development
submodules: true
specs:
rugged (0.19.0)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -268,6 +276,7 @@ DEPENDENCIES
resque
resque-retry
rspec-rails
rugged!
rvm-capistrano
sass
sass-rails
Expand Down
18 changes: 14 additions & 4 deletions lib/git_blame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ def emails_in_branch(build)
end

def changes_since_last_green(build)
output = GitRepo.inside_repo(build.repository) do
# TODO: Push this down into GitRepo and integration test it.
Cocaine::CommandLine.new("git log --no-merges --format='::!::%H|%an <%ae>|%ad|%B::!::' '#{build.previous_successful_build.try(:ref)}...#{build.ref}'").run
GitRepo.inside_repo(build.repository) do |repo|
last_green_ref = build.previous_successful_build.try(:ref)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, not quite as concise as the command line and Cocaine, but it reads fairly well and is less arcane. So on the whole I like it.

current_ref = build.ref
walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_REVERSE)
if last_green_ref
walker.push(last_green_ref)
walker.hide(last_green_ref)
end
walker.push(current_ref)
walker.map do |commit|
author = commit.author
{hash: commit.oid, author: "#{author[:name]} <#{author[:email]}>", date: commit.time, message: commit.message.gsub("\n", " ")}
end
end
parse_git_changes(output)
end

def changes_in_branch(build)
Expand Down
2 changes: 1 addition & 1 deletion lib/git_repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def inside_repo(repository, sync: true)
Dir.chdir(cached_repo_path) do
synchronize_with_remote('origin') if sync

yield
yield Rugged::Repository.new(cached_repo_path)
end
end

Expand Down
48 changes: 38 additions & 10 deletions spec/lib/git_blame_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,25 +69,53 @@
end

describe "#changes_since_last_green" do
let!(:last_successful_build) { FactoryGirl.create(:build, state: :succeeded, project: project, ref: first_commit) }
let(:build) { FactoryGirl.create(:build, project: project, ref: head) }
let(:head) { repo.last_commit.oid }
let(:first_commit) { repo.last_commit.parents.first.parents.first.oid }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know rugged well enough to say whether there is another way to say either "first commit" or a more concise translation of HEAD^^, but this doesn't seem too bad to me.

let(:commiter) { {email: "bilbo@theshire.com", name: 'Bilbo', time: Time.now} }
let(:repo) do
repo = fixture_repo
3.times { |i| commit_to(repo, commiter, commit_message.call(i)) }
repo
end
let!(:frozen_time) { freeze_time! }
subject { GitBlame.changes_since_last_green(build) }
let(:commit_message) { Proc.new {|i| "Making commit number #{i+1} to the repo!" }}

before do
GitBlame.unstub(:changes_since_last_green)
GitRepo.stub(:inside_repo).and_yield(repo)
end

it "should parse the git log message and return a hash of information" do
GitRepo.stub(:inside_repo).and_return("::!::817b88be7488cab5e4f9d9975222db80d8bceb3b|User One <github+uo@squareup.com>|Fri Oct 19 17:43:47 2012 -0700|this is my commit message::!::")
git_changes = subject
git_changes.first[:hash].should == "817b88be7488cab5e4f9d9975222db80d8bceb3b"
git_changes.first[:author].should == "User One <github+uo@squareup.com>"
git_changes.first[:date].should == "Fri Oct 19 17:43:47 2012 -0700"
git_changes.first[:message].should == "this is my commit message"
context "with no prior green build" do
let!(:last_successful_build) { nil }
it "returns all the commits" do
git_changes = subject
git_changes.size.should == 3
end
end

it "should strip new lines in the commit message" do
GitRepo.stub(:inside_repo).and_return("::!::817b88|User One|Fri Oct 19|this is my commit message\nanother line::!::")
it "parses the git log message and return a hash of information" do
git_changes = subject
git_changes.first[:message].should == "this is my commit message another line"
git_changes.size.should == 2
git_changes.first[:hash].should_not == head
git_changes.first[:hash].should_not == first_commit
git_changes.first[:message].should == "Making commit number 2 to the repo!"

git_changes.last[:hash].should == head
git_changes.last[:author].should == "Bilbo <bilbo@theshire.com>"
git_changes.last[:date].to_i.should == frozen_time.to_i
git_changes.last[:message].should == "Making commit number 3 to the repo!"
end

context "with new lines in the commit message" do
let(:commit_message) { Proc.new {|i| "Making commit number #{i+1} to the\nrepo!" }}

it "strips the new lines in the commit message" do
git_changes = subject
git_changes.last[:message].should == "Making commit number 3 to the repo!"
end
end
end

Expand Down
54 changes: 52 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,62 @@
require 'factory_girl'
require 'capybara/rspec'
require 'git_blame'
require 'securerandom'

FIXTURE_PATH = Rails.root.join('spec', 'fixtures')

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

module SpecHelpers
def freeze_time!(frozen_time = Time.now)
Time.stub(:now).and_return(frozen_time)
frozen_time
end
end

module RepositoryFixture
def fixture_repo
repo_path = Rails.root.join("tmp", SecureRandom.hex).to_s
repo = Rugged::Repository.init_at(repo_path)
RepositoryFixture.add_repository(repo_path)
repo
end

def commit_to(repo, commiter, message)
oid = repo.write("This is a blob. #{SecureRandom.hex}", :blob)
builder = Rugged::Tree::Builder.new
builder << { type: :blob, name: "README.md", oid: oid, filemode: 0100644 }

options = {}
options[:tree] = builder.write(repo)

options[:author] = commiter
options[:committer] = commiter
options[:message] = message
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'

Rugged::Commit.create(repo, options)
end

def self.add_repository(path)
@repos ||= []
@repos << path
end

def self.reset_repositories
created_repos = @repos || []
@repos = []
created_repos
end
end

RSpec.configure do |config|
config.mock_with :rspec

config.include(SpecHelpers)
config.include(RepositoryFixture)
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = FIXTURE_PATH

Expand All @@ -32,7 +77,6 @@
config.before :each do
WebMock.disable_net_connect!
JobBase.stub(:enqueue_in)

GitBlame.stub(:git_names_and_emails_since_last_green).and_return("")
GitBlame.stub(:git_names_and_emails_in_branch).and_return("")
GitBlame.stub(:changes_since_last_green).and_return([])
Expand All @@ -43,6 +87,12 @@
ActionMailer::Base.deliveries.clear
end

config.after :each do
RepositoryFixture.reset_repositories.each do |path|
FileUtils.rm_rf(path)
end
end

config.before(:suite) do
test_repo = Rails.root.join('tmp', 'build-partition', 'test-repo-cache')
unless File.exist?(test_repo)
Expand Down