Skip to content

Commit 78ca97b

Browse files
committed
fix(longevity): the alg fails on multiple of insertions and deletions (APP-95)
1 parent 53368e7 commit 78ca97b

File tree

3 files changed

+120
-27
lines changed

3 files changed

+120
-27
lines changed

src/main/kotlin/app/hashers/CodeLongevity.kt

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -233,35 +233,18 @@ class CodeLongevity(private val localRepo: LocalRepo,
233233
}
234234
val lines = files.get(path)!!
235235

236-
// Update the lines array to match the diff's edit list changes.
237-
// Traverse the edit list backwards to keep indices of the edit
238-
// list and the lines array in sync.
239-
val editList = df.toFileHeader(diff).toEditList().asReversed()
240-
for (edit in editList) {
241-
val delStart = edit.getBeginA()
242-
val delEnd = edit.getEndA()
243-
val delCount = edit.getLengthA()
244-
var insStart = edit.getBeginB()
245-
var insEnd = edit.getEndB()
236+
// Update the lines array according to diff insertions.
237+
// Traverse the edit list backwards to keep indices of
238+
// the edit list and the lines array in sync.
239+
val editList = df.toFileHeader(diff).toEditList()
240+
for (edit in editList.asReversed()) {
241+
// Insertion case: track the lines.
246242
val insCount = edit.getLengthB()
247-
Logger.debug("del ($delStart, $delEnd), "
248-
+ "ins ($insStart, $insEnd)")
249-
250-
// Deletion case. Chase down the deleted lines through the
251-
// history.
252-
if (delCount > 0) {
253-
var tmpLines = ArrayList<RevCommitLine>(delCount)
254-
for (idx in delStart .. delEnd - 1) {
255-
tmpLines.add(RevCommitLine(commit, oldPath, idx))
256-
}
257-
258-
// TODO(alex): Approve code change.
259-
// delStart index caused IndexOutOfBoundException.
260-
lines.addAll(tmpLines)
261-
}
262-
263-
// Insertion case. Track it.
264243
if (insCount > 0) {
244+
var insStart = edit.getBeginB()
245+
var insEnd = edit.getEndB()
246+
Logger.debug("ins ($insStart, $insEnd)")
247+
265248
val fileLoader = repo.open(newId)
266249
val fileText = RawText(fileLoader.getBytes())
267250

@@ -276,6 +259,24 @@ class CodeLongevity(private val localRepo: LocalRepo,
276259
}
277260
}
278261

262+
// Update the lines array according to diff deletions.
263+
for (edit in editList) {
264+
// Deletion case. Chase down the deleted lines through the
265+
// history.
266+
val delCount = edit.getLengthA()
267+
if (delCount > 0) {
268+
val delStart = edit.getBeginA()
269+
val delEnd = edit.getEndA()
270+
Logger.debug("del ($delStart, $delEnd)")
271+
272+
var tmpLines = ArrayList<RevCommitLine>(delCount)
273+
for (idx in delStart .. delEnd - 1) {
274+
tmpLines.add(RevCommitLine(commit, oldPath, idx))
275+
}
276+
lines.addAll(delStart, tmpLines)
277+
}
278+
}
279+
279280
// File was renamed, tweak the files map.
280281
if (diff.changeType == DiffEntry.ChangeType.RENAME) {
281282
files.set(oldPath, files.remove(newPath)!!)

src/test/kotlin/test/tests/hashers/CodeLongevityTest.kt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,86 @@ class CodeLongevityTest : Spek({
148148
testRepo.destroy()
149149
}
150150
}
151+
152+
given("'test group #2'") {
153+
154+
val testRepoPath = "../testrepo2"
155+
val testRepo = TestRepo(testRepoPath)
156+
val fileName = "test1.txt"
157+
158+
// t2.1: initial insertion
159+
val fileContent = listOf(
160+
"line1",
161+
"line2",
162+
"line3",
163+
"line4",
164+
"line4",
165+
"line5",
166+
"line6",
167+
"line7",
168+
"line8",
169+
"line9",
170+
"line10",
171+
"line11",
172+
"line12",
173+
"line13",
174+
"line14",
175+
"line15",
176+
"line16",
177+
"line17",
178+
"line18"
179+
)
180+
testRepo.newFile(fileName, fileContent)
181+
val rev1 = testRepo.commit("inital commit")
182+
val lines1 = CodeLongevity(
183+
LocalRepo(testRepoPath), Repo(), MockApi(), testRepo.git).compute()
184+
185+
it("'t2.1: initial insertion'") {
186+
assertEquals(fileContent.size, lines1.size)
187+
for (idx in 0 .. fileContent.size - 1) {
188+
assertCodeLine(fileContent[idx],
189+
rev1, fileName, idx,
190+
rev1, fileName, idx,
191+
lines1[idx])
192+
}
193+
}
194+
195+
// t2.2: ins+del
196+
testRepo.deleteLines(fileName, 15, 18)
197+
testRepo.deleteLines(fileName, 9, 11)
198+
testRepo.deleteLines(fileName, 3, 5)
199+
testRepo.insertLines(fileName, 3, listOf("Proof addition 1"))
200+
testRepo.insertLines(fileName, 7, listOf("Proof addition 2"))
201+
testRepo.insertLines(fileName, 11, listOf("Proof addition 3"))
202+
val rev2 = testRepo.commit("insert+delete")
203+
204+
val lines2 = CodeLongevity(
205+
LocalRepo(testRepoPath), Repo(), MockApi(), testRepo.git).compute()
206+
207+
it("'t2.2: ins+del'") {
208+
assertEquals(22, lines2.size)
209+
assertCodeLine("Proof addition 3", rev2, fileName, 11,
210+
rev2, fileName, 11, lines2[0])
211+
assertCodeLine("Proof addition 2", rev2, fileName, 7,
212+
rev2, fileName, 7, lines2[1])
213+
assertCodeLine("Proof addition 1", rev2, fileName, 3,
214+
rev2, fileName, 3, lines2[2])
215+
assertCodeLine("line1", rev1, fileName, 0,
216+
rev2, fileName, 0, lines2[3])
217+
assertCodeLine("line2",
218+
rev1, fileName, 1, rev2, fileName, 1, lines2[4])
219+
assertCodeLine("line3",
220+
rev1, fileName, 2, rev2, fileName, 2, lines2[5])
221+
assertCodeLine("line4",
222+
rev1, fileName, 3, rev2, fileName, 3, lines2[6])
223+
assertCodeLine("line4",
224+
rev1, fileName, 4, rev2, fileName, 4, lines2[7])
225+
assertCodeLine("line5",
226+
rev1, fileName, 5, rev2, fileName, 5, lines2[8])
227+
}
228+
229+
afterGroup {
230+
testRepo.destroy()
231+
}
232+
}
151233
})

src/test/kotlin/test/utils/TestRepo.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class TestRepo(val repoPath: String) {
5353

5454
var lineIdx = 0
5555
for (line in reader.lines()) {
56+
// Insertion case
5657
if (lineIdx == insIndex) {
5758
for (insLine in insLines) {
5859
tmpWriter.write(insLine)
@@ -64,6 +65,15 @@ class TestRepo(val repoPath: String) {
6465
tmpWriter.newLine()
6566
lineIdx++
6667
}
68+
69+
// Append case
70+
if (lineIdx == insIndex) {
71+
for (insLine in insLines) {
72+
tmpWriter.write(insLine)
73+
tmpWriter.newLine()
74+
}
75+
}
76+
6777
tmpWriter.flush()
6878

6979
val writer = FileWriter(file)

0 commit comments

Comments
 (0)