3c6a4d6363
If a merge request was created with a branch name that also matched a tag name, we'd generate a comparison to or from the tag respectively, rather than the branch. Merging would still use the branch, of course. To avoid this, ensure that when we get the branch heads, we prepend the reference prefix for branches, which will ensure that we generate the correct comparison.
1897 lines
64 KiB
Ruby
1897 lines
64 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe Gitlab::Diff::PositionTracer do
|
|
# Douwe's diary New York City, 2016-06-28
|
|
# --------------------------------------------------------------------------
|
|
#
|
|
# Dear diary,
|
|
#
|
|
# Ideally, we would have a test for every single diff scenario that can
|
|
# occur and that the PositionTracer should correctly trace a position
|
|
# through, across the following variables:
|
|
#
|
|
# - Old diff file type: created, changed, renamed, deleted, unchanged (5)
|
|
# - Old diff line type: added, removed, unchanged (3)
|
|
# - New diff file type: created, changed, renamed, deleted, unchanged (5)
|
|
# - New diff line type: added, removed, unchanged (3)
|
|
# - Old-to-new diff line change: kept, moved, undone (3)
|
|
#
|
|
# This adds up to 5 * 3 * 5 * 3 * 3 = 675 different potential scenarios,
|
|
# and 675 different tests to cover them all. In reality, it would be fewer,
|
|
# since one cannot have a removed line in a created file diff, for example,
|
|
# but for the sake of this diary entry, let's be pessimistic.
|
|
#
|
|
# Writing these tests is a manual and time consuming process, as every test
|
|
# requires the manual construction or finding of a combination of diffs that
|
|
# create the exact diff scenario we are looking for, and can take between
|
|
# 1 and 10 minutes, depending on the farfetchedness of the scenario and
|
|
# complexity of creating it.
|
|
#
|
|
# This means that writing tests to cover all of these scenarios would end up
|
|
# taking between 11 and 112 hours in total, which I do not believe is the
|
|
# best use of my time.
|
|
#
|
|
# A better course of action would be to think of scenarios that are likely
|
|
# to occur, but also potentially tricky to trace correctly, and only cover
|
|
# those, with a few more obvious scenarios thrown in to cover our bases.
|
|
#
|
|
# Unfortunately, I only came to the above realization once I was about
|
|
# 1/5th of the way through the process of writing ALL THE SPECS, having
|
|
# already wasted about 3 hours trying to be thorough.
|
|
#
|
|
# I did find 2 bugs while writing those though, so that's good.
|
|
#
|
|
# In any case, all of this means that the tests below will be extremely
|
|
# (excessively, unjustifiably) thorough for scenarios where "the file was
|
|
# created in the old diff" and then drop off to comparitively lackluster
|
|
# testing of other scenarios.
|
|
#
|
|
# I did still try to cover most of the obvious and potentially tricky
|
|
# scenarios, though.
|
|
|
|
include RepoHelpers
|
|
|
|
let(:project) { create(:project, :repository) }
|
|
let(:current_user) { project.owner }
|
|
let(:repository) { project.repository }
|
|
let(:file_name) { "test-file" }
|
|
let(:new_file_name) { "#{file_name}-new" }
|
|
let(:second_file_name) { "#{file_name}-2" }
|
|
let(:branch_name) { "position-tracer-test" }
|
|
|
|
let(:old_diff_refs) { raise NotImplementedError }
|
|
let(:new_diff_refs) { raise NotImplementedError }
|
|
let(:change_diff_refs) { raise NotImplementedError }
|
|
let(:old_position) { raise NotImplementedError }
|
|
|
|
let(:position_tracer) { described_class.new(project: project, old_diff_refs: old_diff_refs, new_diff_refs: new_diff_refs) }
|
|
subject { position_tracer.trace(old_position) }
|
|
|
|
def diff_refs(base_commit, head_commit)
|
|
Gitlab::Diff::DiffRefs.new(base_sha: base_commit.id, head_sha: head_commit.id)
|
|
end
|
|
|
|
def text_position_attrs
|
|
[:old_line, :new_line]
|
|
end
|
|
|
|
def position(attrs = {})
|
|
attrs.reverse_merge!(
|
|
diff_refs: old_diff_refs
|
|
)
|
|
Gitlab::Diff::Position.new(attrs)
|
|
end
|
|
|
|
def expect_new_position(attrs, result = subject)
|
|
aggregate_failures("expect new position #{attrs.inspect}") do
|
|
if attrs.nil?
|
|
expect(result[:outdated]).to be_truthy
|
|
else
|
|
expect(result[:outdated]).to be_falsey
|
|
|
|
new_position = result[:position]
|
|
expect(new_position).not_to be_nil
|
|
|
|
expect(new_position.diff_refs).to eq(new_diff_refs)
|
|
|
|
attrs.each do |attr, value|
|
|
if text_position_attrs.include?(attr)
|
|
expect(new_position.formatter.send(attr)).to eq(value)
|
|
else
|
|
expect(new_position.send(attr)).to eq(value)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def expect_change_position(attrs, result = subject)
|
|
aggregate_failures("expect change position #{attrs.inspect}") do
|
|
expect(result[:outdated]).to be_truthy
|
|
|
|
change_position = result[:position]
|
|
if attrs.nil? || attrs.empty?
|
|
expect(change_position).to be_nil
|
|
else
|
|
expect(change_position).not_to be_nil
|
|
|
|
expect(change_position.diff_refs).to eq(change_diff_refs)
|
|
|
|
attrs.each do |attr, value|
|
|
if text_position_attrs.include?(attr)
|
|
expect(change_position.formatter.send(attr)).to eq(value)
|
|
else
|
|
expect(change_position.send(attr)).to eq(value)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def create_branch(new_name, branch_name)
|
|
CreateBranchService.new(project, current_user).execute(new_name, branch_name)
|
|
end
|
|
|
|
def create_file(branch_name, file_name, content)
|
|
Files::CreateService.new(
|
|
project,
|
|
current_user,
|
|
start_branch: branch_name,
|
|
branch_name: branch_name,
|
|
commit_message: "Create file",
|
|
file_path: file_name,
|
|
file_content: content
|
|
).execute
|
|
project.commit(branch_name)
|
|
end
|
|
|
|
def update_file(branch_name, file_name, content)
|
|
Files::UpdateService.new(
|
|
project,
|
|
current_user,
|
|
start_branch: branch_name,
|
|
branch_name: branch_name,
|
|
commit_message: "Update file",
|
|
file_path: file_name,
|
|
file_content: content
|
|
).execute
|
|
project.commit(branch_name)
|
|
end
|
|
|
|
def delete_file(branch_name, file_name)
|
|
Files::DeleteService.new(
|
|
project,
|
|
current_user,
|
|
start_branch: branch_name,
|
|
branch_name: branch_name,
|
|
commit_message: "Delete file",
|
|
file_path: file_name
|
|
).execute
|
|
project.commit(branch_name)
|
|
end
|
|
|
|
let(:initial_commit) do
|
|
create_branch(branch_name, "master")[:branch].name
|
|
project.commit(branch_name)
|
|
end
|
|
|
|
describe "#trace" do
|
|
describe "diff scenarios" do
|
|
let(:create_file_commit) do
|
|
initial_commit
|
|
|
|
create_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
B
|
|
C
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:create_second_file_commit) do
|
|
create_file_commit
|
|
|
|
create_file(
|
|
branch_name,
|
|
second_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
D
|
|
E
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:update_line_commit) do
|
|
create_second_file_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
BB
|
|
C
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:update_second_file_line_commit) do
|
|
update_line_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
second_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
D
|
|
EE
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:move_line_commit) do
|
|
update_second_file_line_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
BB
|
|
A
|
|
C
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:add_second_file_line_commit) do
|
|
move_line_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
second_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
D
|
|
EE
|
|
F
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:move_second_file_line_commit) do
|
|
add_second_file_line_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
second_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
D
|
|
F
|
|
EE
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:delete_line_commit) do
|
|
move_second_file_line_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
BB
|
|
A
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:delete_second_file_line_commit) do
|
|
delete_line_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
second_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
D
|
|
F
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:delete_file_commit) do
|
|
delete_second_file_line_commit
|
|
|
|
delete_file(branch_name, file_name)
|
|
end
|
|
|
|
let(:rename_file_commit) do
|
|
delete_file_commit
|
|
|
|
create_file(
|
|
branch_name,
|
|
new_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
BB
|
|
A
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:update_line_again_commit) do
|
|
rename_file_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
new_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
BB
|
|
AA
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:move_line_again_commit) do
|
|
update_line_again_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
new_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
AA
|
|
BB
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:delete_line_again_commit) do
|
|
move_line_again_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
new_file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
AA
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
context "when the file was created in the old diff" do
|
|
context "when the file is created in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, create_second_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_line_commit, delete_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 3) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 3,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the file is changed in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_line_commit, move_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 3) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 - A
|
|
# 2 1 BB
|
|
# 2 + A
|
|
# 3 3 C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_line_commit, move_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 - A
|
|
# 2 1 BB
|
|
# 2 + A
|
|
# 3 3 C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 3) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 BB
|
|
# 2 2 A
|
|
# 3 - C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 3,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the file is renamed in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, rename_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
#
|
|
# new diff:
|
|
# file_name -> new_file_name
|
|
# 1 1 BB
|
|
# 2 2 A
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: nil,
|
|
new_line: 2
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
#
|
|
# new diff:
|
|
# file_name -> new_file_name
|
|
# 1 1 BB
|
|
# 2 - A
|
|
# 2 + AA
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
old_path: file_name,
|
|
new_path: new_file_name,
|
|
old_line: old_position.new_line,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, move_line_again_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
#
|
|
# new diff:
|
|
# file_name -> new_file_name
|
|
# 1 + AA
|
|
# 1 2 BB
|
|
# 2 - A
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
old_path: file_name,
|
|
new_path: new_file_name,
|
|
old_line: 1,
|
|
new_line: 2
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
|
|
let(:change_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
#
|
|
# new diff:
|
|
# file_name -> new_file_name
|
|
# 1 1 BB
|
|
# 2 - A
|
|
# 2 + AA
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: new_file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the file is deleted in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
#
|
|
# new diff:
|
|
# 1 - BB
|
|
# 2 - A
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 - BB
|
|
# 2 - A
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_line_commit, delete_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 - BB
|
|
# 2 - A
|
|
# 3 - C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_line_commit, delete_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(create_file_commit, delete_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 - A
|
|
# 2 - BB
|
|
# 3 - C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 3) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 - BB
|
|
# 2 - A
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 3,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the file is unchanged in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, create_second_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 2 B
|
|
# 3 3 C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: nil,
|
|
new_line: 2
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_line_commit, update_second_file_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 2 BB
|
|
# 3 3 C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: nil,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(move_line_commit, move_second_file_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 BB
|
|
# 2 2 A
|
|
# 3 3 C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: nil,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_line_commit, update_second_file_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(create_file_commit, update_second_file_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 2 BB
|
|
# 3 3 C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_second_file_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, delete_second_file_line_commit) }
|
|
let(:old_position) { position(new_path: file_name, new_line: 3) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
# 3 + C
|
|
#
|
|
# new diff:
|
|
# 1 1 BB
|
|
# 2 2 A
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 3,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the file was changed in the old diff" do
|
|
context "when the file is created in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 1 2 A
|
|
# 2 - B
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed or deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, create_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, create_file_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 1 2 A
|
|
# 2 - B
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
# 3 + C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 1,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the position pointed at a deleted line in the old diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(create_file_commit, initial_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 2,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the position pointed at an unchanged line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 1, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 1, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 1 2 A
|
|
# 2 - B
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + BB
|
|
# 2 + A
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 BB
|
|
# 2 2 A
|
|
# 3 - C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + BB
|
|
# 3 + C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed or deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 3, new_line: 3) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 1 2 A
|
|
# 2 - B
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 + A
|
|
# 2 + B
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 3,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the file is changed in the new diff" do
|
|
context "when the position pointed at an added line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_second_file_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
old_path: old_position.old_path,
|
|
new_path: old_position.new_path,
|
|
old_line: nil,
|
|
new_line: old_position.new_line
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the file's content was changed between the old and the new diff" do
|
|
context "when that line was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 1 2 A
|
|
# 2 - B
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 1 BB
|
|
# 2 2 A
|
|
# 3 - C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
old_path: old_position.old_path,
|
|
new_path: old_position.new_path,
|
|
old_line: 1,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was moved between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_line_commit, move_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 - A
|
|
# 2 1 BB
|
|
# 2 + A
|
|
# 3 3 C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
old_path: old_position.old_path,
|
|
new_path: old_position.new_path,
|
|
old_line: 2,
|
|
new_line: 1
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when that line was changed or deleted between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:change_diff_refs) { diff_refs(move_line_commit, update_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
|
|
|
|
# old diff:
|
|
# 1 + BB
|
|
# 1 2 A
|
|
# 2 - B
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
|
|
it "returns the position of the change" do
|
|
expect_change_position(
|
|
old_path: file_name,
|
|
new_path: file_name,
|
|
old_line: 1,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the position pointed at a deleted line in the old diff" do
|
|
context "when the file's content was unchanged between the old and the new diff" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_second_file_line_commit) }
|
|
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
|
|
it "returns the new position" do
|
|
expect_new_position(
|
|
old_path: old_position.old_path,
|
|
new_path: old_position.new_path,
|
|
old_line: old_position.old_line,
|
|
new_line: nil
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "typical use scenarios" do
|
|
let(:second_branch_name) { "#{branch_name}-2" }
|
|
|
|
def expect_new_positions(old_attrs, new_attrs)
|
|
old_positions = old_attrs.map do |old_attrs|
|
|
position(old_attrs)
|
|
end
|
|
|
|
new_positions = old_positions.map do |old_position|
|
|
position_tracer.trace(old_position)
|
|
end
|
|
|
|
aggregate_failures do
|
|
new_positions.zip(new_attrs).each do |new_position, new_attrs|
|
|
if new_attrs&.delete(:change)
|
|
expect_change_position(new_attrs, new_position)
|
|
else
|
|
expect_new_position(new_attrs, new_position)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
let(:create_file_commit) do
|
|
initial_commit
|
|
|
|
create_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
B
|
|
C
|
|
D
|
|
E
|
|
F
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:second_create_file_commit) do
|
|
create_file_commit
|
|
|
|
create_branch(second_branch_name, branch_name)
|
|
|
|
update_file(
|
|
second_branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
Z
|
|
Z
|
|
Z
|
|
A
|
|
B
|
|
C
|
|
D
|
|
E
|
|
F
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:update_file_commit) do
|
|
second_create_file_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
C
|
|
DD
|
|
E
|
|
F
|
|
G
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:update_file_again_commit) do
|
|
update_file_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
BB
|
|
C
|
|
D
|
|
E
|
|
FF
|
|
G
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
describe "simple push of new commit" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_file_commit, update_file_again_commit) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 3 2 C
|
|
# 4 - D
|
|
# 3 + DD
|
|
# 5 4 E
|
|
# 6 5 F
|
|
# 6 + G
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
# 4 4 D
|
|
# 5 5 E
|
|
# 6 - F
|
|
# 6 + FF
|
|
# 7 + G
|
|
|
|
it "returns the new positions" do
|
|
old_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 }, # C
|
|
{ old_path: file_name, old_line: 4 }, # - D
|
|
{ new_path: file_name, new_line: 3 }, # + DD
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 }, # E
|
|
{ old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 }, # F
|
|
{ new_path: file_name, new_line: 6 }, # + G
|
|
]
|
|
|
|
new_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
|
|
{ old_path: file_name, old_line: 2 },
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 },
|
|
{ new_path: file_name, new_line: 4, change: true },
|
|
{ new_path: file_name, old_line: 3, change: true },
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
|
|
{ new_path: file_name, old_line: 5, change: true },
|
|
{ new_path: file_name, new_line: 7 }
|
|
]
|
|
|
|
expect_new_positions(old_position_attrs, new_position_attrs)
|
|
end
|
|
end
|
|
|
|
describe "force push to overwrite last commit" do
|
|
let(:second_create_file_commit) do
|
|
create_file_commit
|
|
|
|
create_branch(second_branch_name, branch_name)
|
|
|
|
update_file(
|
|
second_branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
BB
|
|
C
|
|
D
|
|
E
|
|
FF
|
|
G
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, second_create_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_file_commit, second_create_file_commit) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 3 2 C
|
|
# 4 - D
|
|
# 3 + DD
|
|
# 5 4 E
|
|
# 6 5 F
|
|
# 6 + G
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
# 4 4 D
|
|
# 5 5 E
|
|
# 6 - F
|
|
# 6 + FF
|
|
# 7 + G
|
|
|
|
it "returns the new positions" do
|
|
old_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 }, # C
|
|
{ old_path: file_name, old_line: 4 }, # - D
|
|
{ new_path: file_name, new_line: 3 }, # + DD
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 }, # E
|
|
{ old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 }, # F
|
|
{ new_path: file_name, new_line: 6 }, # + G
|
|
]
|
|
|
|
new_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
|
|
{ old_path: file_name, old_line: 2 },
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 },
|
|
{ new_path: file_name, new_line: 4, change: true },
|
|
{ old_path: file_name, old_line: 3, change: true },
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
|
|
{ old_path: file_name, old_line: 5, change: true },
|
|
{ new_path: file_name, new_line: 7 }
|
|
]
|
|
|
|
expect_new_positions(old_position_attrs, new_position_attrs)
|
|
end
|
|
end
|
|
|
|
describe "force push to delete last commit" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_file_again_commit, update_file_commit) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
# 4 4 D
|
|
# 5 5 E
|
|
# 6 - F
|
|
# 6 + FF
|
|
# 7 + G
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 3 2 C
|
|
# 4 - D
|
|
# 3 + DD
|
|
# 5 4 E
|
|
# 6 5 F
|
|
# 6 + G
|
|
|
|
it "returns the new positions" do
|
|
old_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ new_path: file_name, new_line: 2 }, # + BB
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
|
|
{ old_path: file_name, old_line: 6 }, # - F
|
|
{ new_path: file_name, new_line: 6 }, # + FF
|
|
{ new_path: file_name, new_line: 7 }, # + G
|
|
]
|
|
|
|
new_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
|
|
{ old_path: file_name, old_line: 2 },
|
|
{ old_path: file_name, old_line: 2, change: true },
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 },
|
|
{ old_path: file_name, old_line: 4, change: true },
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 },
|
|
{ new_path: file_name, new_line: 5, change: true },
|
|
{ old_path: file_name, old_line: 6, change: true },
|
|
{ new_path: file_name, new_line: 6 }
|
|
]
|
|
|
|
expect_new_positions(old_position_attrs, new_position_attrs)
|
|
end
|
|
end
|
|
|
|
describe "rebase on top of target branch" do
|
|
let(:second_update_file_commit) do
|
|
update_file_commit
|
|
|
|
update_file(
|
|
second_branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
Z
|
|
Z
|
|
Z
|
|
A
|
|
C
|
|
DD
|
|
E
|
|
F
|
|
G
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:update_file_again_commit) do
|
|
second_update_file_commit
|
|
|
|
update_file(
|
|
branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
A
|
|
BB
|
|
C
|
|
D
|
|
E
|
|
FF
|
|
G
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:overwrite_update_file_again_commit) do
|
|
update_file_again_commit
|
|
|
|
update_file(
|
|
second_branch_name,
|
|
file_name,
|
|
<<-CONTENT.strip_heredoc
|
|
Z
|
|
Z
|
|
Z
|
|
A
|
|
BB
|
|
C
|
|
D
|
|
E
|
|
FF
|
|
G
|
|
CONTENT
|
|
)
|
|
end
|
|
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, overwrite_update_file_again_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_file_again_commit, overwrite_update_file_again_commit) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
# 4 4 D
|
|
# 5 5 E
|
|
# 6 - F
|
|
# 6 + FF
|
|
# 7 + G
|
|
#
|
|
# new diff:
|
|
# 1 + Z
|
|
# 2 + Z
|
|
# 3 + Z
|
|
# 1 4 A
|
|
# 2 - B
|
|
# 5 + BB
|
|
# 3 6 C
|
|
# 4 7 D
|
|
# 5 8 E
|
|
# 6 - F
|
|
# 9 + FF
|
|
# 0 + G
|
|
|
|
it "returns the new positions" do
|
|
old_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ new_path: file_name, new_line: 2 }, # + BB
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
|
|
{ old_path: file_name, old_line: 6 }, # - F
|
|
{ new_path: file_name, new_line: 6 }, # + FF
|
|
{ new_path: file_name, new_line: 7 }, # + G
|
|
]
|
|
|
|
new_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 4 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ new_path: file_name, new_line: 5 }, # + BB
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 6 }, # C
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 7 }, # D
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 8 }, # E
|
|
{ old_path: file_name, old_line: 6 }, # - F
|
|
{ new_path: file_name, new_line: 9 }, # + FF
|
|
{ new_path: file_name, new_line: 10 }, # + G
|
|
]
|
|
|
|
expect_new_positions(old_position_attrs, new_position_attrs)
|
|
end
|
|
end
|
|
|
|
describe "merge of target branch" do
|
|
let(:merge_commit) do
|
|
second_create_file_commit
|
|
|
|
merge_request = create(:merge_request, source_branch: second_branch_name, target_branch: branch_name, source_project: project)
|
|
|
|
repository.merge(current_user, merge_request.diff_head_sha, merge_request, "Merge branches")
|
|
|
|
project.commit(branch_name)
|
|
end
|
|
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
|
|
let(:new_diff_refs) { diff_refs(create_file_commit, merge_commit) }
|
|
let(:change_diff_refs) { diff_refs(update_file_again_commit, merge_commit) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
# 4 4 D
|
|
# 5 5 E
|
|
# 6 - F
|
|
# 6 + FF
|
|
# 7 + G
|
|
#
|
|
# new diff:
|
|
# 1 + Z
|
|
# 2 + Z
|
|
# 3 + Z
|
|
# 1 4 A
|
|
# 2 - B
|
|
# 5 + BB
|
|
# 3 6 C
|
|
# 4 7 D
|
|
# 5 8 E
|
|
# 6 - F
|
|
# 9 + FF
|
|
# 0 + G
|
|
|
|
it "returns the new positions" do
|
|
old_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ new_path: file_name, new_line: 2 }, # + BB
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
|
|
{ old_path: file_name, old_line: 6 }, # - F
|
|
{ new_path: file_name, new_line: 6 }, # + FF
|
|
{ new_path: file_name, new_line: 7 }, # + G
|
|
]
|
|
|
|
new_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 4 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ new_path: file_name, new_line: 5 }, # + BB
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 6 }, # C
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 7 }, # D
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 8 }, # E
|
|
{ old_path: file_name, old_line: 6 }, # - F
|
|
{ new_path: file_name, new_line: 9 }, # + FF
|
|
{ new_path: file_name, new_line: 10 }, # + G
|
|
]
|
|
|
|
expect_new_positions(old_position_attrs, new_position_attrs)
|
|
end
|
|
end
|
|
|
|
describe "changing target branch" do
|
|
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
|
|
let(:new_diff_refs) { diff_refs(update_file_commit, update_file_again_commit) }
|
|
let(:change_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
|
|
|
|
# old diff:
|
|
# 1 1 A
|
|
# 2 - B
|
|
# 2 + BB
|
|
# 3 3 C
|
|
# 4 4 D
|
|
# 5 5 E
|
|
# 6 - F
|
|
# 6 + FF
|
|
# 7 + G
|
|
#
|
|
# new diff:
|
|
# 1 1 A
|
|
# 2 + BB
|
|
# 2 3 C
|
|
# 3 - DD
|
|
# 4 + D
|
|
# 4 5 E
|
|
# 5 - F
|
|
# 6 + FF
|
|
# 7 G
|
|
|
|
it "returns the new positions" do
|
|
old_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
|
|
{ old_path: file_name, old_line: 2 }, # - B
|
|
{ new_path: file_name, new_line: 2 }, # + BB
|
|
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
|
|
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
|
|
{ old_path: file_name, old_line: 6 }, # - F
|
|
{ new_path: file_name, new_line: 6 }, # + FF
|
|
{ new_path: file_name, new_line: 7 }, # + G
|
|
]
|
|
|
|
new_position_attrs = [
|
|
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
|
|
{ old_path: file_name, old_line: 2, change: true },
|
|
{ new_path: file_name, new_line: 2 },
|
|
{ old_path: file_name, new_path: file_name, old_line: 2, new_line: 3 },
|
|
{ new_path: file_name, new_line: 4 },
|
|
{ old_path: file_name, new_path: file_name, old_line: 4, new_line: 5 },
|
|
{ old_path: file_name, old_line: 5 },
|
|
{ new_path: file_name, new_line: 6 },
|
|
{ new_path: file_name, new_line: 7 }
|
|
]
|
|
|
|
expect_new_positions(old_position_attrs, new_position_attrs)
|
|
end
|
|
end
|
|
end
|
|
end
|