Skip to content

Fix for Bad character encoding. #391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
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: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ And here are the operations that will need to write to your git repository.
g.merge(g.branch('master'))
g.merge([branch1, branch2])

g.merge_base('branch1', 'branch2')

r = g.add_remote(name, uri) # Git::Remote
r = g.add_remote(name, Git::Base) # Git::Remote

Expand Down
8 changes: 8 additions & 0 deletions lib/git/base/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ def tag(tag_name)
Git::Object.new(self, tag_name, 'tag', true)
end

# Find as good common ancestors as possible for a merge
# example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true)
# returns Array<Git::Object::Commit>
def merge_base(*args)
shas = self.lib.merge_base(*args)
shas.map { |sha| gcommit(sha) }
end

end

end
Expand Down
2 changes: 1 addition & 1 deletion lib/git/diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def process_full_diff
if @full_diff.encoding.name != "UTF-8"
full_diff_utf8_encoded = @full_diff.encode("UTF-8", "binary", { :invalid => :replace, :undef => :replace })
else
full_diff_utf8_encoded = @full_diff
full_diff_utf8_encoded = @full_diff.encode("UTF-8", "UTF-8", { :invalid => :replace, :undef => :replace })
end
full_diff_utf8_encoded.split("\n").each do |line|
if m = /^diff --git a\/(.*?) b\/(.*?)/.match(line)
Expand Down
16 changes: 16 additions & 0 deletions lib/git/lib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,21 @@ def merge(branch, message = nil)
command('merge', arr_opts)
end

def merge_base(*args)
opts = args.last.is_a?(Hash) ? args.pop : {}

arg_opts = []

arg_opts << '--octopus' if opts[:octopus]
arg_opts << '--independent' if opts[:independent]
arg_opts << '--fork-point' if opts[:fork_point]
arg_opts << '--all' if opts[:all]

arg_opts += args

command('merge-base', arg_opts).lines.map(&:strip)
end

def unmerged
unmerged = []
command_lines('diff', ["--cached"]).each do |line|
Expand Down Expand Up @@ -747,6 +762,7 @@ def fetch(remote, opts)
arr_opts << opts[:ref] if opts[:ref]
arr_opts << '--tags' if opts[:t] || opts[:tags]
arr_opts << '--prune' if opts[:p] || opts[:prune]
arr_opts << '--unshallow' if opts[:unshallow]

command('fetch', arr_opts)
end
Expand Down
11 changes: 10 additions & 1 deletion tests/units/test_lib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ def setup
set_file_paths
@lib = Git.open(@wdir).lib
end


def test_fetch_unshallow
in_temp_dir do |dir|
git = Git.clone("file://#{@wdir}", "shallow", path: dir, depth: 1).lib
assert_equal(1, git.log_commits.length)
git.fetch("file://#{@wdir}", unshallow: true)
assert_equal(71, git.log_commits.length)
end
end

def test_commit_data
data = @lib.commit_data('1cc8667014381')
assert_equal('scott Chacon <schacon@agadorsparticus.corp.reactrix.com> 1194561188 -0800', data['author'])
Expand Down
144 changes: 144 additions & 0 deletions tests/units/test_merge_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env ruby

require File.dirname(__FILE__) + '/../test_helper'

class TestMergeBase < Test::Unit::TestCase
def setup
set_file_paths
end

def test_branch_and_master_merge_base
in_temp_dir do |_path|
repo = Git.clone(@wbare, 'branch_merge_test')
Dir.chdir('branch_merge_test') do
true_ancestor_sha = repo.gcommit('master').sha

add_commit(repo, 'new_branch')
add_commit(repo, 'master')

ancestors = repo.merge_base('master', 'new_branch')
assert_equal(ancestors.size, 1) # there is only one true ancestor
assert_equal(ancestors.first.sha, true_ancestor_sha) # proper common ancestor
end
end
end

def test_branch_and_master_independent_merge_base
in_temp_dir do |_path|
repo = Git.clone(@wbare, 'branch_merge_test')
Dir.chdir('branch_merge_test') do
true_ancestor_sha = repo.gcommit('master').sha

add_commit(repo, 'new_branch')
add_commit(repo, 'master')

independent_commits = repo.merge_base(true_ancestor_sha, 'master', 'new_branch', independent: true)
assert_equal(independent_commits.size, 2) # both new master and a branch are unreachable from each other
true_independent_commits_shas = [repo.gcommit('master').sha, repo.gcommit('new_branch').sha]
assert_equal(independent_commits.map(&:sha).sort, true_independent_commits_shas.sort)
end
end
end

def test_branch_and_master_fork_point_merge_base
in_temp_dir do |_path|
repo = Git.clone(@wbare, 'branch_merge_test')
Dir.chdir('branch_merge_test') do
add_commit(repo, 'master')

true_ancestor_sha = repo.gcommit('master').sha

add_commit(repo, 'new_branch')

repo.reset_hard(repo.gcommit('HEAD^'))

add_commit(repo, 'master')

ancestors = repo.merge_base('master', 'new_branch', fork_point: true)
assert_equal(ancestors.size, 1) # there is only one true ancestor
assert_equal(ancestors.first.sha, true_ancestor_sha) # proper common ancestor
end
end
end

def test_branch_and_master_all_merge_base
in_temp_dir do |_path|
repo = Git.clone(@wbare, 'branch_merge_test')
Dir.chdir('branch_merge_test') do
add_commit(repo, 'new_branch_1')

first_commit_sha = repo.gcommit('new_branch_1').sha

add_commit(repo, 'new_branch_2')

second_commit_sha = repo.gcommit('new_branch_2').sha

repo.branch('new_branch_1').merge('new_branch_2')
repo.branch('new_branch_2').merge('new_branch_1^')

add_commit(repo, 'new_branch_1')
add_commit(repo, 'new_branch_2')

true_ancestors_shas = [first_commit_sha, second_commit_sha]

ancestors = repo.merge_base('new_branch_1', 'new_branch_2')
assert_equal(ancestors.size, 1) # default behavior returns only one ancestor
assert(true_ancestors_shas.include?(ancestors.first.sha))

all_ancestors = repo.merge_base('new_branch_1', 'new_branch_2', all: true)
assert_equal(all_ancestors.size, 2) # there are two best ancestors in such case
assert_equal(all_ancestors.map(&:sha).sort, true_ancestors_shas.sort)
end
end
end

def test_branches_and_master_merge_base
in_temp_dir do |_path|
repo = Git.clone(@wbare, 'branch_merge_test')
Dir.chdir('branch_merge_test') do
add_commit(repo, 'new_branch_1')
add_commit(repo, 'master')

non_octopus_ancestor_sha = repo.gcommit('master').sha

add_commit(repo, 'new_branch_2')
add_commit(repo, 'master')

ancestors = repo.merge_base('master', 'new_branch_1', 'new_branch_2')
assert_equal(ancestors.size, 1) # there is only one true ancestor
assert_equal(ancestors.first.sha, non_octopus_ancestor_sha) # proper common ancestor
end
end
end

def test_branches_and_master_octopus_merge_base
in_temp_dir do |_path|
repo = Git.clone(@wbare, 'branch_merge_test')
Dir.chdir('branch_merge_test') do
true_ancestor_sha = repo.gcommit('master').sha

add_commit(repo, 'new_branch_1')
add_commit(repo, 'master')
add_commit(repo, 'new_branch_2')
add_commit(repo, 'master')

ancestors = repo.merge_base('master', 'new_branch_1', 'new_branch_2', octopus: true)
assert_equal(ancestors.size, 1) # there is only one true ancestor
assert_equal(ancestors.first.sha, true_ancestor_sha) # proper common ancestor
end
end
end

private

def add_commit(repo, branch_name)
@commit_number ||= 0
@commit_number += 1

repo.branch(branch_name).in_branch("test commit #{@commit_number}") do
new_file("new_file_#{@commit_number}", 'hello')
repo.add
true
end
end
end