Skip to content

Commit 655d27c

Browse files
#416 Fix - Files of the same name in sub-folders will be considered a… (#455)
* #416 Fix - Files of the same name in sub-folders will be considered as different files * #416 Fix - Adding more testcases and covering all possible special characters --------- Co-authored-by: Owen Nelson <58788812+tw-owen-nelson@users.noreply.github.com>
1 parent a7a57f9 commit 655d27c

File tree

6 files changed

+141
-28
lines changed

6 files changed

+141
-28
lines changed

checksumcalculator/checksumcalculator_test.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,48 @@ func TestNewChecksumCalculator(t *testing.T) {
3434
t.Run("should return CollectiveChecksum when existing file name pattern is sent", func(t *testing.T) {
3535
gitAdditions := []gitrepo.Addition{
3636
{
37-
Path: "GitRepoPath1",
37+
Path: "GitRepoPath1/GitRepoName1",
3838
Name: "GitRepoName1",
3939
},
4040
}
41-
expectedCC := "54bbf09e5c906e2d7cc0808729f8120cfa3c4bad3fb6a85689ae23ca00e5a3c8"
42-
fileNamePattern := "*RepoName1"
41+
expectedCC := "19250a996e1200d33e91454bc662efae7682410e5347cfc56b0ff386dfbc10ae"
42+
fileNamePattern := "GitRepoPath1/"
4343
cc := NewChecksumCalculator(defaultSHA256Hasher, gitAdditions)
4444

4545
actualCC := cc.CalculateCollectiveChecksumForPattern(fileNamePattern)
4646

4747
assert.Equal(t, expectedCC, actualCC)
4848
})
49+
50+
t.Run("should return the files own CollectiveChecksum when same file name is present in subfolders", func(t *testing.T) {
51+
gitAdditions := []gitrepo.Addition{
52+
{
53+
Path: "hello.txt",
54+
Name: "hello.txt",
55+
},
56+
{
57+
Path: "subfolder/hello.txt",
58+
Name: "hello.txt",
59+
},
60+
}
61+
hello_expectedCC := "9d30c2e4bcf181bba07374cc416f1892d89918038bce5172776475347c4d2d69"
62+
fileNamePattern1 := "hello.txt"
63+
cc1 := NewChecksumCalculator(defaultSHA256Hasher, gitAdditions)
64+
actualCC := cc1.CalculateCollectiveChecksumForPattern(fileNamePattern1)
65+
assert.Equal(t, hello_expectedCC, actualCC)
66+
67+
subfolder_hello_expectedCC := "6c779c16bcc2e63c659be7649a531650210d6b96ae590a146f9ccdca383587f6"
68+
fileNamePattern2 := "subfolder/hello.txt"
69+
cc2 := NewChecksumCalculator(defaultSHA256Hasher, gitAdditions)
70+
subfolder_actualCC := cc2.CalculateCollectiveChecksumForPattern(fileNamePattern2)
71+
assert.Equal(t, subfolder_hello_expectedCC, subfolder_actualCC)
72+
73+
all_txt_expectedCC := "aba77c9077539130e21a8f275fc5f1f43b7f0589e392bc89e4b96c578f0a9184"
74+
fileNamePattern3 := "*.txt"
75+
cc3 := NewChecksumCalculator(defaultSHA256Hasher, gitAdditions)
76+
all_txt_actualCC := cc3.CalculateCollectiveChecksumForPattern(fileNamePattern3)
77+
assert.Equal(t, all_txt_expectedCC, all_txt_actualCC)
78+
})
4979
}
5080

5181
func TestDefaultChecksumCalculator_SuggestTalismanRC(t *testing.T) {

cmd/acceptance_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ private.pem
5050
ignore_detectors: []
5151
`
5252

53+
const talismanRCForHelloTxtFile = `
54+
fileignoreconfig:
55+
- filename: hello.txt
56+
checksum: edf37f1d33525d1710c3f5dc3437778c483def1d2e98b5a3495fc627eb1be588
57+
ignore_detectors: []
58+
`
59+
5360
func init() {
5461
git_testing.Logger = logrus.WithField("Environment", "Debug")
5562
git_testing.Logger.Debug("Acceptance test started")
@@ -268,6 +275,23 @@ func TestPatternFindsSecretInNestedFile(t *testing.T) {
268275
})
269276
}
270277

278+
func TestFilesWithSameNameWithinRepositoryAreHandledAsSeparateFiles(t *testing.T) {
279+
withNewTmpGitRepo(func(git *git_testing.GitTesting) {
280+
git.SetupBaselineFiles("simple-file", "some-dir/hello.txt")
281+
git.CreateFileWithContents("hello.txt", awsAccessKeyIDExample)
282+
git.AddAndcommit("*", "Start of Scan before talismanrc")
283+
assert.Equal(t, 1, runTalismanInPrePushMode(git), "Expected run() to return 1 since secret is detected in hello")
284+
git.CreateFileWithContents(".talismanrc", talismanRCForHelloTxtFile)
285+
286+
git.AppendFileContent("some-dir/hello.txt", "More safe content")
287+
assert.Equal(t, 0, runTalismanInPrePushMode(git), "Expected run() to return 0 since hello checksum is added to fileignoreconfig in talismanrc")
288+
git.AddAndcommit("some-dir/hello.txt", "Start of second scan")
289+
assert.Equal(t, 0, runTalismanInPrePushMode(git), "Expected run() to return 0 since hello in subfolder was only changed")
290+
git.AppendFileContent("hello.txt", "More safe content in unsafe file")
291+
git.AddAndcommit("hello.txt", "Start of third scan - new hash is required")
292+
assert.Equal(t, 1, runTalismanInPrePushMode(git), "Expected run() to return 1 since hello checksum is changed")
293+
})
294+
}
271295
func TestIgnoreHistoryDoesNotDetectRemovedSecrets(t *testing.T) {
272296
withNewTmpGitRepo(func(git *git_testing.GitTesting) {
273297
options.Debug = false

detector/helpers/checksum_compare_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ func TestChecksumCompare_IsScanNotRequired(t *testing.T) {
4242
},
4343
},
4444
}
45+
addition := gitrepo.Addition{Name: "some.txt", Path: "some.txt"}
4546
cc := NewChecksumCompare(checksumCalculator, &ignoreConfig)
46-
addition := gitrepo.Addition{Name: "some.txt"}
4747
checksumCalculator.EXPECT().CalculateCollectiveChecksumForPattern("some.txt").Return("sha1")
4848

4949
required := cc.IsScanNotRequired(addition)

gitrepo/gitrepo.go

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,27 @@ import (
1212
log "github.com/sirupsen/logrus"
1313
)
1414

15-
//FilePath represents the absolute path of an added file
15+
// FilePath represents the absolute path of an added file
1616
type FilePath string
1717

18-
//FileName represents the base name of an added file
18+
// FileName represents the base name of an added file
1919
type FileName string
2020

21-
//Addition represents the end state of a file
21+
// Addition represents the end state of a file
2222
type Addition struct {
2323
Path FilePath
2424
Name FileName
2525
Commits []string
2626
Data []byte
2727
}
2828

29-
//GitRepo represents a Git repository located at the absolute path represented by root
29+
// GitRepo represents a Git repository located at the absolute path represented by root
3030
type GitRepo struct {
3131
root string
3232
}
3333

34-
//RepoLocatedAt returns a new GitRepo with it's root located at the location specified by the argument.
35-
//If the argument is not an absolute path, it will be turned into one.
34+
// RepoLocatedAt returns a new GitRepo with it's root located at the location specified by the argument.
35+
// If the argument is not an absolute path, it will be turned into one.
3636
func RepoLocatedAt(path string) GitRepo {
3737
absoluteRoot, _ := filepath.Abs(path)
3838
return GitRepo{absoluteRoot}
@@ -117,7 +117,7 @@ func MatchGitDiffLine(gitDiffString string) (bool, string) {
117117
return false, ""
118118
}
119119

120-
//StagedAdditions returns the files staged for commit in a GitRepo
120+
// StagedAdditions returns the files staged for commit in a GitRepo
121121
func (repo GitRepo) StagedAdditions() []Addition {
122122
files := repo.stagedFiles()
123123
result := make([]Addition, len(files))
@@ -132,7 +132,7 @@ func (repo GitRepo) StagedAdditions() []Addition {
132132
return result
133133
}
134134

135-
//AllAdditions returns all the outgoing additions and modifications in a GitRepo. This does not include files that were deleted.
135+
// AllAdditions returns all the outgoing additions and modifications in a GitRepo. This does not include files that were deleted.
136136
func (repo GitRepo) AllAdditions() []Addition {
137137
result := string(repo.executeRepoCommand("git", "rev-parse", "--abbrev-ref", "origin/HEAD"))
138138
log.Debugf("Result of getting default branch %v", result)
@@ -141,7 +141,7 @@ func (repo GitRepo) AllAdditions() []Addition {
141141
return repo.AdditionsWithinRange(oldCommit, newCommit)
142142
}
143143

144-
//AdditionsWithinRange returns the outgoing additions and modifications in a GitRepo that are in the given commit range. This does not include files that were deleted.
144+
// AdditionsWithinRange returns the outgoing additions and modifications in a GitRepo that are in the given commit range. This does not include files that were deleted.
145145
func (repo GitRepo) AdditionsWithinRange(oldCommit string, newCommit string) []Addition {
146146
files := repo.outgoingNonDeletedFiles(oldCommit, newCommit)
147147
result := make([]Addition, len(files))
@@ -157,7 +157,7 @@ func (repo GitRepo) AdditionsWithinRange(oldCommit string, newCommit string) []A
157157
return result
158158
}
159159

160-
//NewAddition returns a new Addition for a file with supplied name and contents
160+
// NewAddition returns a new Addition for a file with supplied name and contents
161161
func NewAddition(filePath string, content []byte) Addition {
162162
return Addition{
163163
Path: FilePath(filePath),
@@ -166,7 +166,7 @@ func NewAddition(filePath string, content []byte) Addition {
166166
}
167167
}
168168

169-
//NewScannerAddition returns an new Addition for a file with supplied contents and all of the commits the file is in
169+
// NewScannerAddition returns an new Addition for a file with supplied contents and all of the commits the file is in
170170
func NewScannerAddition(filePath string, commits []string, content []byte) Addition {
171171
return Addition{
172172
Path: FilePath(filePath),
@@ -176,9 +176,9 @@ func NewScannerAddition(filePath string, commits []string, content []byte) Addit
176176
}
177177
}
178178

179-
//CheckIfFileExists checks if the file exists on the file system. Does not look into the file contents
180-
//Returns TRUE if file exists
181-
//Returns FALSE if the file is not found
179+
// CheckIfFileExists checks if the file exists on the file system. Does not look into the file contents
180+
// Returns TRUE if file exists
181+
// Returns FALSE if the file is not found
182182
func (repo GitRepo) CheckIfFileExists(fileName string) bool {
183183
filepath := path.Join(repo.root, fileName)
184184
if _, err := os.Stat(filepath); os.IsNotExist(err) {
@@ -187,18 +187,21 @@ func (repo GitRepo) CheckIfFileExists(fileName string) bool {
187187
return true
188188
}
189189

190-
//Matches states whether the addition matches the given pattern.
191-
//If the pattern ends in a path separator, then all files inside a directory with that name are matched. However, files with that name itself will not be matched.
192-
//If a pattern contains the path separator in any other location, the match works according to the pattern logic of the default golang glob mechanism
193-
//If there is no path separator anywhere in the pattern, the pattern is matched against the base name of the file. Thus, the pattern will match files with that name anywhere in the repository.
190+
// Matches states whether the addition matches the given pattern.
191+
// If the pattern ends in a path separator, then all files inside a directory with that name are matched. However, files with that name itself will not be matched.
192+
// If a pattern contains the path separator in any other location, the match works according to the pattern logic of the default golang glob mechanism
193+
// If there are other special characters in the pattern, the pattern is matched against the base name of the file. Thus, the pattern will match files with that pattern anywhere in the repository.
194+
// If there are no special characters in the pattern, then it means exact filename is provided as pattern like file.txt. Thus, the pattern is matched against the file path so that not all files with the same name in the repo are not returned.
194195
func (a Addition) Matches(pattern string) bool {
195196
var result bool
196-
if pattern[len(pattern)-1] == '/' {
197+
if pattern[len(pattern)-1] == '/' { // If the pattern ends in a path separator, then all files inside a directory with that name are matched. However, files with that name itself will not be matched.
197198
result = strings.HasPrefix(string(a.Path), pattern)
198-
} else if strings.ContainsRune(pattern, '/') {
199+
} else if strings.ContainsRune(pattern, '/') { // If a pattern contains the path separator in any other location, the match works according to the pattern logic of the default golang glob mechanism
199200
result, _ = path.Match(pattern, string(a.Path))
200-
} else {
201+
} else if strings.ContainsAny(pattern, "*?[]\\") { // If there are other special characters in the pattern, the pattern is matched against the base name of the file. Thus, the pattern will match files with that pattern anywhere in the repository.
201202
result, _ = path.Match(pattern, string(a.Name))
203+
} else { // If there are no special characters in the pattern, then it means exact filename is provided as pattern like file.txt. Thus, the pattern is matched against the file path so that not all files with the same name in the repo are not returned.
204+
result = strings.Compare(string(a.Path), pattern) == 0
202205
}
203206
log.WithFields(log.Fields{
204207
"pattern": pattern,
@@ -208,7 +211,7 @@ func (a Addition) Matches(pattern string) bool {
208211
return result
209212
}
210213

211-
//TrackedFilesAsAdditions returns all of the tracked files in a GitRepo as Additions
214+
// TrackedFilesAsAdditions returns all of the tracked files in a GitRepo as Additions
212215
func (repo GitRepo) TrackedFilesAsAdditions() []Addition {
213216
trackedFilePaths := repo.trackedFilePaths()
214217
var additions []Addition

gitrepo/gitrepo_test.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,67 @@ func TestMatchShouldAllowWildcardPatternMatches(t *testing.T) {
215215
assert.False(t, file3.Matches(pattern))
216216
}
217217

218+
func TestMatchShouldMatchExactFileIfNoPatternIsProvided(t *testing.T) {
219+
file1 := Addition{Path: "bigfile", Name: "bigfile"}
220+
file2 := Addition{Path: "subfolder/bigfile", Name: "bigfile"}
221+
file3 := Addition{Path: "somefile", Name: "somefile"}
222+
pattern := "bigfile"
223+
224+
assert.True(t, file1.Matches(pattern))
225+
assert.False(t, file2.Matches(pattern))
226+
assert.False(t, file3.Matches(pattern))
227+
}
228+
229+
func TestMatchShouldAllowStarPattern(t *testing.T) {
230+
file1 := Addition{Path: "GitRepoPath1/File1.txt", Name: "File1.txt"}
231+
file2 := Addition{Path: "GitRepoPath1/File2.txt", Name: "File2.txt"}
232+
file3 := Addition{Path: "GitRepoPath1/somefile", Name: "somefile"}
233+
file4 := Addition{Path: "somefile.jpg", Name: "somefile.jpg"}
234+
file5 := Addition{Path: "somefile.txt", Name: "somefile.txt"}
235+
file6 := Addition{Path: "File1.txt", Name: "File1.txt"}
236+
file7 := Addition{Path: "File3.txt", Name: "File3.txt"}
237+
238+
pattern := "GitRepoPath1/*.txt"
239+
240+
assert.True(t, file1.Matches(pattern))
241+
assert.True(t, file2.Matches(pattern))
242+
assert.False(t, file3.Matches(pattern))
243+
assert.False(t, file4.Matches(pattern))
244+
assert.False(t, file5.Matches(pattern))
245+
246+
pattern1 := "*.txt"
247+
assert.True(t, file1.Matches(pattern1))
248+
assert.True(t, file2.Matches(pattern1))
249+
assert.False(t, file3.Matches(pattern1))
250+
assert.False(t, file4.Matches(pattern1))
251+
assert.True(t, file5.Matches(pattern1))
252+
253+
pattern2 := "File?.txt"
254+
assert.True(t, file1.Matches(pattern2))
255+
assert.True(t, file2.Matches(pattern2))
256+
assert.True(t, file6.Matches(pattern2))
257+
258+
pattern3 := "File[1].txt"
259+
assert.True(t, file1.Matches(pattern3))
260+
assert.False(t, file2.Matches(pattern3))
261+
assert.True(t, file6.Matches(pattern3))
262+
263+
pattern4 := "File[1-2].txt"
264+
assert.True(t, file1.Matches(pattern4))
265+
assert.True(t, file2.Matches(pattern4))
266+
assert.True(t, file6.Matches(pattern4))
267+
assert.False(t, file7.Matches(pattern4))
268+
269+
pattern5 := "File\\1.txt"
270+
assert.True(t, file1.Matches(pattern5))
271+
assert.True(t, file6.Matches(pattern5))
272+
}
273+
218274
func setupOriginAndClones(originLocation, cloneLocation string) (*git_testing.GitTesting, GitRepo) {
219275
origin := RepoLocatedAt(originLocation)
220276
git := git_testing.Init(origin.root)
221277
git.SetupBaselineFiles("a.txt", filepath.Join("alice", "bob", "b.txt"))
222-
git.SetupBaselineFiles("c.txt", filepath.Join( "folder b","c.txt"))
278+
git.SetupBaselineFiles("c.txt", filepath.Join("folder b", "c.txt"))
223279
cwd, _ := os.Getwd()
224280
gitClone := git.GitClone(filepath.Join(cwd, cloneLocation))
225281
return gitClone, RepoLocatedAt(cloneLocation)

talismanrc/scopes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var knownScopes = map[string][]string{
55
"go": {"makefile", "go.mod", "go.sum", "Gopkg.toml", "Gopkg.lock", "glide.yaml", "glide.lock"},
66
"images": {"*.jpeg", "*.jpg", "*.png", "*.tiff", "*.bmp"},
77
"bazel": {"*.bzl"},
8-
"terraform": {".terraform.lock.hcl"},
8+
"terraform": {".terraform.lock.hcl", "*.terraform.lock.hcl"},
99
"php": {"composer.lock"},
1010
"python": {"poetry.lock", "Pipfile.lock", "requirements.txt"},
1111
}

0 commit comments

Comments
 (0)