2019-09-06 05:20:09 +03:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2019-09-06 05:20:09 +03:00
package gitdiff
2016-01-04 00:26:46 +03:00
import (
2019-11-28 12:05:57 +03:00
"fmt"
2020-11-22 01:41:24 +03:00
"strconv"
2018-08-06 07:43:22 +03:00
"strings"
2016-01-31 19:16:29 +03:00
"testing"
2017-06-12 18:01:09 +03:00
2022-01-20 02:26:57 +03:00
"code.gitea.io/gitea/models/db"
2022-06-13 12:37:59 +03:00
issues_model "code.gitea.io/gitea/models/issues"
2021-11-12 17:36:47 +03:00
"code.gitea.io/gitea/models/unittest"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2021-08-31 07:16:23 +03:00
"code.gitea.io/gitea/modules/git"
2021-07-24 19:03:58 +03:00
"code.gitea.io/gitea/modules/json"
2019-03-14 19:09:53 +03:00
"code.gitea.io/gitea/modules/setting"
2021-07-24 19:03:58 +03:00
2017-06-12 18:01:09 +03:00
dmp "github.com/sergi/go-diff/diffmatchpatch"
2018-08-06 07:43:22 +03:00
"github.com/stretchr/testify/assert"
2016-01-04 00:26:46 +03:00
)
2016-01-09 22:05:21 +03:00
func TestDiffToHTML ( t * testing . T ) {
2022-07-23 14:28:02 +03:00
assert . Equal ( t , "foo <span class=\"added-code\">bar</span> biz" , diffToHTML ( nil , [ ] dmp . Diff {
2018-03-30 02:21:27 +03:00
{ Type : dmp . DiffEqual , Text : "foo " } ,
{ Type : dmp . DiffInsert , Text : "bar" } ,
{ Type : dmp . DiffDelete , Text : " baz" } ,
{ Type : dmp . DiffEqual , Text : " biz" } ,
2022-07-23 14:28:02 +03:00
} , DiffLineAdd ) )
2016-01-04 00:26:46 +03:00
2022-07-23 14:28:02 +03:00
assert . Equal ( t , "foo <span class=\"removed-code\">bar</span> biz" , diffToHTML ( nil , [ ] dmp . Diff {
2018-03-30 02:21:27 +03:00
{ Type : dmp . DiffEqual , Text : "foo " } ,
{ Type : dmp . DiffDelete , Text : "bar" } ,
{ Type : dmp . DiffInsert , Text : " baz" } ,
{ Type : dmp . DiffEqual , Text : " biz" } ,
2022-07-23 14:28:02 +03:00
} , DiffLineDel ) )
2016-01-04 00:26:46 +03:00
}
2018-08-06 07:43:22 +03:00
2021-11-20 16:50:00 +03:00
func TestParsePatch_skipTo ( t * testing . T ) {
type testcase struct {
name string
gitdiff string
wantErr bool
addition int
deletion int
oldFilename string
filename string
skipTo string
}
tests := [ ] testcase {
{
name : "readme.md2readme.md" ,
gitdiff : ` diff -- git "a/A \\ B" "b/A \\ B"
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
diff -- git "\\a/README.md" "\\b/README.md"
-- - "\\a/README.md"
++ + "\\b/README.md"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
` ,
addition : 4 ,
deletion : 1 ,
filename : "README.md" ,
oldFilename : "README.md" ,
skipTo : "README.md" ,
} ,
{
name : "A \\ B" ,
gitdiff : ` diff -- git "a/A \\ B" "b/A \\ B"
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off ` ,
addition : 4 ,
deletion : 1 ,
filename : "A \\ B" ,
oldFilename : "A \\ B" ,
skipTo : "A \\ B" ,
} ,
{
name : "A \\ B" ,
gitdiff : ` diff -- git "\\a/README.md" "\\b/README.md"
-- - "\\a/README.md"
++ + "\\b/README.md"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
diff -- git "a/A \\ B" "b/A \\ B"
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off ` ,
addition : 4 ,
deletion : 1 ,
filename : "A \\ B" ,
oldFilename : "A \\ B" ,
skipTo : "A \\ B" ,
} ,
{
name : "readme.md2readme.md" ,
gitdiff : ` diff -- git "a/A \\ B" "b/A \\ B"
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
diff -- git "a/A \\ B" "b/A \\ B"
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
diff -- git "\\a/README.md" "\\b/README.md"
-- - "\\a/README.md"
++ + "\\b/README.md"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
` ,
addition : 4 ,
deletion : 1 ,
filename : "README.md" ,
oldFilename : "README.md" ,
skipTo : "README.md" ,
} ,
}
for _ , testcase := range tests {
t . Run ( testcase . name , func ( t * testing . T ) {
2023-10-03 13:30:41 +03:00
got , err := ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( testcase . gitdiff ) , testcase . skipTo )
2021-11-20 16:50:00 +03:00
if ( err != nil ) != testcase . wantErr {
t . Errorf ( "ParsePatch(%q) error = %v, wantErr %v" , testcase . name , err , testcase . wantErr )
return
}
gotMarshaled , _ := json . MarshalIndent ( got , "" , " " )
if got . NumFiles != 1 {
t . Errorf ( "ParsePath(%q) did not receive 1 file:\n%s" , testcase . name , string ( gotMarshaled ) )
return
}
if got . TotalAddition != testcase . addition {
t . Errorf ( "ParsePath(%q) does not have correct totalAddition %d, wanted %d" , testcase . name , got . TotalAddition , testcase . addition )
}
if got . TotalDeletion != testcase . deletion {
t . Errorf ( "ParsePath(%q) did not have correct totalDeletion %d, wanted %d" , testcase . name , got . TotalDeletion , testcase . deletion )
}
file := got . Files [ 0 ]
if file . Addition != testcase . addition {
t . Errorf ( "ParsePath(%q) does not have correct file addition %d, wanted %d" , testcase . name , file . Addition , testcase . addition )
}
if file . Deletion != testcase . deletion {
t . Errorf ( "ParsePath(%q) did not have correct file deletion %d, wanted %d" , testcase . name , file . Deletion , testcase . deletion )
}
if file . OldName != testcase . oldFilename {
t . Errorf ( "ParsePath(%q) did not have correct OldName %q, wanted %q" , testcase . name , file . OldName , testcase . oldFilename )
}
if file . Name != testcase . filename {
t . Errorf ( "ParsePath(%q) did not have correct Name %q, wanted %q" , testcase . name , file . Name , testcase . filename )
}
} )
}
}
2020-09-09 16:08:40 +03:00
func TestParsePatch_singlefile ( t * testing . T ) {
type testcase struct {
name string
gitdiff string
wantErr bool
addition int
deletion int
oldFilename string
filename string
}
tests := [ ] testcase {
{
name : "readme.md2readme.md" ,
2020-10-14 07:49:33 +03:00
gitdiff : ` diff -- git "\\a/README.md" "\\b/README.md"
-- - "\\a/README.md"
++ + "\\b/README.md"
2020-09-09 16:08:40 +03:00
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off
` ,
2020-10-14 07:49:33 +03:00
addition : 4 ,
deletion : 1 ,
filename : "README.md" ,
oldFilename : "README.md" ,
2020-09-09 16:08:40 +03:00
} ,
{
name : "A \\ B" ,
gitdiff : ` diff -- git "a/A \\ B" "b/A \\ B"
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off ` ,
2020-10-14 07:49:33 +03:00
addition : 4 ,
deletion : 1 ,
filename : "A \\ B" ,
oldFilename : "A \\ B" ,
2020-09-09 16:08:40 +03:00
} ,
{
name : "really weird filename" ,
2020-10-14 07:49:33 +03:00
gitdiff : ` diff -- git "\\a/a b/file b/a a/file" "\\b/a b/file b/a a/file"
2020-09-09 16:08:40 +03:00
index d2186f1 . . f5c8ed2 100644
2020-11-22 01:41:24 +03:00
-- - "\\a/a b/file b/a a/file" ` + `
++ + "\\b/a b/file b/a a/file" ` + `
2020-09-09 16:08:40 +03:00
@ @ - 1 , 3 + 1 , 2 @ @
Create a weird file .
2020-11-22 01:41:24 +03:00
` + `
2020-09-09 16:08:40 +03:00
- and what does diff do here ?
\ No newline at end of file ` ,
addition : 0 ,
deletion : 1 ,
filename : "a b/file b/a a/file" ,
oldFilename : "a b/file b/a a/file" ,
} ,
{
name : "delete file with blanks" ,
2020-10-14 07:49:33 +03:00
gitdiff : ` diff -- git "\\a/file with blanks" "\\b/file with blanks"
2020-09-09 16:08:40 +03:00
deleted file mode 100644
index 898651 a . .0000000
2020-11-22 01:41:24 +03:00
-- - "\\a/file with blanks" ` + `
2020-09-09 16:08:40 +03:00
++ + / dev / null
@ @ - 1 , 5 + 0 , 0 @ @
- a blank file
-
- has a couple o line
-
- the 5 th line is the last
` ,
2020-10-14 07:49:33 +03:00
addition : 0 ,
deletion : 5 ,
filename : "file with blanks" ,
oldFilename : "file with blanks" ,
2020-09-09 16:08:40 +03:00
} ,
{
name : "rename a—as" ,
gitdiff : ` diff -- git "a/\360\243\220\265b\342\200\240vs" "b/a\342\200\224as"
similarity index 100 %
rename from "\360\243\220\265b\342\200\240vs"
rename to "a\342\200\224as"
` ,
addition : 0 ,
deletion : 0 ,
oldFilename : "𣐵b†vs" ,
filename : "a—as" ,
} ,
{
name : "rename with spaces" ,
2020-10-14 07:49:33 +03:00
gitdiff : ` diff -- git "\\a/a b/file b/a a/file" "\\b/a b/a a/file b/b file"
2020-09-09 16:08:40 +03:00
similarity index 100 %
rename from a b / file b / a a / file
rename to a b / a a / file b / b file
` ,
oldFilename : "a b/file b/a a/file" ,
filename : "a b/a a/file b/b file" ,
} ,
2021-02-27 21:46:14 +03:00
{
name : "ambiguous deleted" ,
gitdiff : ` diff -- git a / b b / b b / b b / b
deleted file mode 100644
index 92e798 b . .0000000
-- - a / b b / b ` + "\t" + `
++ + / dev / null
@ @ - 1 + 0 , 0 @ @
- b b / b
` ,
oldFilename : "b b/b" ,
filename : "b b/b" ,
addition : 0 ,
deletion : 1 ,
} ,
{
name : "ambiguous addition" ,
gitdiff : ` diff -- git a / b b / b b / b b / b
new file mode 100644
index 0000000. .92e798 b
-- - / dev / null
++ + b / b b / b ` + "\t" + `
@ @ - 0 , 0 + 1 @ @
+ b b / b
` ,
oldFilename : "b b/b" ,
filename : "b b/b" ,
addition : 1 ,
deletion : 0 ,
} ,
{
name : "rename" ,
gitdiff : ` diff -- git a / b b / b b / b b / b b / b b / b
similarity index 100 %
rename from b b / b b / b b / b b / b
rename to b
` ,
oldFilename : "b b/b b/b b/b b/b" ,
filename : "b" ,
} ,
{
name : "ambiguous 1" ,
gitdiff : ` diff -- git a / b b / b b / b b / b b / b b / b
similarity index 100 %
rename from b b / b b / b b / b b / b
rename to b
` ,
oldFilename : "b b/b b/b b/b b/b" ,
filename : "b" ,
} ,
{
name : "ambiguous 2" ,
gitdiff : ` diff -- git a / b b / b b / b b / b b / b b / b
similarity index 100 %
rename from b b / b b / b b / b
rename to b b / b
` ,
oldFilename : "b b/b b/b b/b" ,
filename : "b b/b" ,
} ,
2020-10-16 20:13:18 +03:00
{
name : "minuses-and-pluses" ,
gitdiff : ` diff -- git a / minuses - and - pluses b / minuses - and - pluses
index 6961180. .9 ba1a00 100644
-- - a / minuses - and - pluses
++ + b / minuses - and - pluses
@ @ - 1 , 4 + 1 , 4 @ @
-- - 1 st line
- ++ 2 nd line
-- - 3 rd line
- ++ 4 th line
++ + 1 st line
+ -- 2 nd line
++ + 3 rd line
+ -- 4 th line
` ,
oldFilename : "minuses-and-pluses" ,
filename : "minuses-and-pluses" ,
addition : 4 ,
deletion : 4 ,
} ,
2020-09-09 16:08:40 +03:00
}
for _ , testcase := range tests {
t . Run ( testcase . name , func ( t * testing . T ) {
2023-10-03 13:30:41 +03:00
got , err := ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( testcase . gitdiff ) , "" )
2020-09-09 16:08:40 +03:00
if ( err != nil ) != testcase . wantErr {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePatch(%q) error = %v, wantErr %v" , testcase . name , err , testcase . wantErr )
2020-09-09 16:08:40 +03:00
return
}
2021-07-24 19:03:58 +03:00
2021-03-02 00:08:10 +03:00
gotMarshaled , _ := json . MarshalIndent ( got , "" , " " )
2020-09-09 16:08:40 +03:00
if got . NumFiles != 1 {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) did not receive 1 file:\n%s" , testcase . name , string ( gotMarshaled ) )
2020-09-09 16:08:40 +03:00
return
}
if got . TotalAddition != testcase . addition {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) does not have correct totalAddition %d, wanted %d" , testcase . name , got . TotalAddition , testcase . addition )
2020-09-09 16:08:40 +03:00
}
if got . TotalDeletion != testcase . deletion {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) did not have correct totalDeletion %d, wanted %d" , testcase . name , got . TotalDeletion , testcase . deletion )
2020-09-09 16:08:40 +03:00
}
file := got . Files [ 0 ]
if file . Addition != testcase . addition {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) does not have correct file addition %d, wanted %d" , testcase . name , file . Addition , testcase . addition )
2020-09-09 16:08:40 +03:00
}
if file . Deletion != testcase . deletion {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) did not have correct file deletion %d, wanted %d" , testcase . name , file . Deletion , testcase . deletion )
2020-09-09 16:08:40 +03:00
}
if file . OldName != testcase . oldFilename {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) did not have correct OldName %q, wanted %q" , testcase . name , file . OldName , testcase . oldFilename )
2020-09-09 16:08:40 +03:00
}
if file . Name != testcase . filename {
2021-02-27 21:46:14 +03:00
t . Errorf ( "ParsePath(%q) did not have correct Name %q, wanted %q" , testcase . name , file . Name , testcase . filename )
2020-09-09 16:08:40 +03:00
}
} )
}
2020-11-22 01:41:24 +03:00
// Test max lines
diffBuilder := & strings . Builder { }
2022-01-20 20:46:10 +03:00
diff := ` diff -- git a / newfile2 b / newfile2
2020-11-22 01:41:24 +03:00
new file mode 100644
index 0000000. .6 bb8f39
-- - / dev / null
++ + b / newfile2
@ @ - 0 , 0 + 1 , 35 @ @
`
diffBuilder . WriteString ( diff )
for i := 0 ; i < 35 ; i ++ {
diffBuilder . WriteString ( "+line" + strconv . Itoa ( i ) + "\n" )
}
diff = diffBuilder . String ( )
2023-10-03 13:30:41 +03:00
result , err := ParsePatch ( db . DefaultContext , 20 , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff ) , "" )
2020-11-22 01:41:24 +03:00
if err != nil {
t . Errorf ( "There should not be an error: %v" , err )
}
if ! result . Files [ 0 ] . IsIncomplete {
t . Errorf ( "Files should be incomplete! %v" , result . Files [ 0 ] )
}
2023-10-03 13:30:41 +03:00
result , err = ParsePatch ( db . DefaultContext , 40 , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff ) , "" )
2020-11-22 01:41:24 +03:00
if err != nil {
t . Errorf ( "There should not be an error: %v" , err )
}
if result . Files [ 0 ] . IsIncomplete {
t . Errorf ( "Files should not be incomplete! %v" , result . Files [ 0 ] )
}
2023-10-03 13:30:41 +03:00
result , err = ParsePatch ( db . DefaultContext , 40 , 5 , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff ) , "" )
2020-11-22 01:41:24 +03:00
if err != nil {
t . Errorf ( "There should not be an error: %v" , err )
}
if ! result . Files [ 0 ] . IsIncomplete {
t . Errorf ( "Files should be incomplete! %v" , result . Files [ 0 ] )
}
// Test max characters
diff = ` diff -- git a / newfile2 b / newfile2
new file mode 100644
index 0000000. .6 bb8f39
-- - / dev / null
++ + b / newfile2
@ @ - 0 , 0 + 1 , 35 @ @
`
diffBuilder . Reset ( )
diffBuilder . WriteString ( diff )
for i := 0 ; i < 33 ; i ++ {
diffBuilder . WriteString ( "+line" + strconv . Itoa ( i ) + "\n" )
}
diffBuilder . WriteString ( "+line33" )
for i := 0 ; i < 512 ; i ++ {
diffBuilder . WriteString ( "0123456789ABCDEF" )
}
diffBuilder . WriteByte ( '\n' )
diffBuilder . WriteString ( "+line" + strconv . Itoa ( 34 ) + "\n" )
diffBuilder . WriteString ( "+line" + strconv . Itoa ( 35 ) + "\n" )
diff = diffBuilder . String ( )
2023-10-03 13:30:41 +03:00
result , err = ParsePatch ( db . DefaultContext , 20 , 4096 , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff ) , "" )
2020-11-22 01:41:24 +03:00
if err != nil {
t . Errorf ( "There should not be an error: %v" , err )
}
if ! result . Files [ 0 ] . IsIncomplete {
t . Errorf ( "Files should be incomplete! %v" , result . Files [ 0 ] )
}
2023-10-03 13:30:41 +03:00
result , err = ParsePatch ( db . DefaultContext , 40 , 4096 , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff ) , "" )
2020-11-22 01:41:24 +03:00
if err != nil {
t . Errorf ( "There should not be an error: %v" , err )
}
if ! result . Files [ 0 ] . IsIncomplete {
t . Errorf ( "Files should be incomplete! %v" , result . Files [ 0 ] )
}
diff = ` diff -- git "a/README.md" "b/README.md"
2019-03-14 19:09:53 +03:00
-- - a / README . md
++ + b / README . md
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off `
2023-10-03 13:30:41 +03:00
_ , err = ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff ) , "" )
2019-03-14 19:09:53 +03:00
if err != nil {
t . Errorf ( "ParsePatch failed: %s" , err )
}
2022-01-20 20:46:10 +03:00
diff2 := ` diff -- git "a/A \\ B" "b/A \\ B"
2019-03-14 19:09:53 +03:00
-- - "a/A \\ B"
++ + "b/A \\ B"
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off `
2023-10-03 13:30:41 +03:00
_ , err = ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff2 ) , "" )
2019-03-14 19:09:53 +03:00
if err != nil {
t . Errorf ( "ParsePatch failed: %s" , err )
}
2022-01-20 20:46:10 +03:00
diff2a := ` diff -- git "a/A \\ B" b / A / B
2020-08-22 18:07:37 +03:00
-- - "a/A \\ B"
++ + b / A / B
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off `
2023-10-03 13:30:41 +03:00
_ , err = ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff2a ) , "" )
2020-08-22 18:07:37 +03:00
if err != nil {
t . Errorf ( "ParsePatch failed: %s" , err )
}
2022-01-20 20:46:10 +03:00
diff3 := ` diff -- git a / README . md b / README . md
2019-03-14 19:09:53 +03:00
-- - a / README . md
++ + b / README . md
@ @ - 1 , 3 + 1 , 6 @ @
# gitea - github - migrator
+
+ Build Status
- Latest Release
Docker Pulls
+ cut off
+ cut off `
2023-10-03 13:30:41 +03:00
_ , err = ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( diff3 ) , "" )
2019-03-14 19:09:53 +03:00
if err != nil {
t . Errorf ( "ParsePatch failed: %s" , err )
}
}
2018-08-06 07:43:22 +03:00
func setupDefaultDiff ( ) * Diff {
return & Diff {
Files : [ ] * DiffFile {
{
Name : "README.md" ,
Sections : [ ] * DiffSection {
{
Lines : [ ] * DiffLine {
{
LeftIdx : 4 ,
RightIdx : 4 ,
} ,
} ,
} ,
} ,
} ,
} ,
}
}
2022-01-20 20:46:10 +03:00
2023-06-21 19:08:12 +03:00
func TestDiff_LoadCommentsNoOutdated ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2019-09-06 05:20:09 +03:00
2022-08-16 05:22:25 +03:00
issue := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : 2 } )
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
2018-08-06 07:43:22 +03:00
diff := setupDefaultDiff ( )
2023-06-21 19:08:12 +03:00
assert . NoError ( t , diff . LoadComments ( db . DefaultContext , issue , user , false ) )
2018-08-06 07:43:22 +03:00
assert . Len ( t , diff . Files [ 0 ] . Sections [ 0 ] . Lines [ 0 ] . Comments , 2 )
}
2023-06-21 19:08:12 +03:00
func TestDiff_LoadCommentsWithOutdated ( t * testing . T ) {
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
issue := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : 2 } )
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
diff := setupDefaultDiff ( )
assert . NoError ( t , diff . LoadComments ( db . DefaultContext , issue , user , true ) )
assert . Len ( t , diff . Files [ 0 ] . Sections [ 0 ] . Lines [ 0 ] . Comments , 3 )
}
2018-08-06 07:43:22 +03:00
func TestDiffLine_CanComment ( t * testing . T ) {
assert . False ( t , ( & DiffLine { Type : DiffLineSection } ) . CanComment ( ) )
2022-06-13 12:37:59 +03:00
assert . False ( t , ( & DiffLine { Type : DiffLineAdd , Comments : [ ] * issues_model . Comment { { Content : "bla" } } } ) . CanComment ( ) )
2018-08-06 07:43:22 +03:00
assert . True ( t , ( & DiffLine { Type : DiffLineAdd } ) . CanComment ( ) )
assert . True ( t , ( & DiffLine { Type : DiffLineDel } ) . CanComment ( ) )
assert . True ( t , ( & DiffLine { Type : DiffLinePlain } ) . CanComment ( ) )
}
func TestDiffLine_GetCommentSide ( t * testing . T ) {
2022-06-13 12:37:59 +03:00
assert . Equal ( t , "previous" , ( & DiffLine { Comments : [ ] * issues_model . Comment { { Line : - 3 } } } ) . GetCommentSide ( ) )
assert . Equal ( t , "proposed" , ( & DiffLine { Comments : [ ] * issues_model . Comment { { Line : 3 } } } ) . GetCommentSide ( ) )
2018-08-06 07:43:22 +03:00
}
2019-11-28 12:05:57 +03:00
func TestGetDiffRangeWithWhitespaceBehavior ( t * testing . T ) {
2022-03-29 22:13:41 +03:00
gitRepo , err := git . OpenRepository ( git . DefaultContext , "./testdata/academic-module" )
2021-08-31 07:16:23 +03:00
if ! assert . NoError ( t , err ) {
return
}
defer gitRepo . Close ( )
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
for _ , behavior := range [ ] git . TrustedCmdArgs { { "-w" } , { "--ignore-space-at-eol" } , { "-b" } , nil } {
2023-10-03 13:30:41 +03:00
diffs , err := GetDiff ( db . DefaultContext , gitRepo ,
2021-11-21 19:51:08 +03:00
& DiffOptions {
AfterCommitID : "bd7063cc7c04689c4d082183d32a604ed27a24f9" ,
BeforeCommitID : "559c156f8e0178b71cb44355428f24001b08fc68" ,
MaxLines : setting . Git . MaxGitDiffLines ,
MaxLineCharacters : setting . Git . MaxGitDiffLineCharacters ,
MaxFiles : setting . Git . MaxGitDiffFiles ,
WhitespaceBehavior : behavior ,
} )
2019-11-28 12:05:57 +03:00
assert . NoError ( t , err , fmt . Sprintf ( "Error when diff with %s" , behavior ) )
for _ , f := range diffs . Files {
assert . True ( t , len ( f . Sections ) > 0 , fmt . Sprintf ( "%s should have sections" , f . Name ) )
}
}
}
2021-02-14 17:51:00 +03:00
2021-11-07 20:52:50 +03:00
func TestNoCrashes ( t * testing . T ) {
type testcase struct {
gitdiff string
}
tests := [ ] testcase {
{
gitdiff : "diff --git \n--- a\t\n" ,
} ,
{
gitdiff : "diff --git \"0\n" ,
} ,
}
for _ , testcase := range tests {
// It shouldn't crash, so don't care about the output.
2023-10-03 13:30:41 +03:00
ParsePatch ( db . DefaultContext , setting . Git . MaxGitDiffLines , setting . Git . MaxGitDiffLineCharacters , setting . Git . MaxGitDiffFiles , strings . NewReader ( testcase . gitdiff ) , "" )
2021-11-07 20:52:50 +03:00
}
}