22{
33 using GitVersion . Helpers ;
44 using System ;
5+ using System . Collections . Generic ;
56 using System . IO ;
67 using System . Security . Cryptography ;
78 using System . Text ;
9+ using System . Linq ;
810
9- public class GitVersionCacheKeyFactory
11+ class GitVersionCacheKeyFactory
1012 {
1113 public static GitVersionCacheKey Create ( IFileSystem fileSystem , GitPreparer gitPreparer , Config overrideConfig )
1214 {
@@ -23,10 +25,101 @@ private static string GetGitSystemHash(GitPreparer gitPreparer, IFileSystem file
2325 {
2426 var dotGitDirectory = gitPreparer . GetDotGitDirectory ( ) ;
2527
26- // Maybe using timestamp in .git/refs directory is enough?
27- var lastGitRefsChangedTicks = fileSystem . GetLastDirectoryWrite ( Path . Combine ( dotGitDirectory , "refs" ) ) ;
28+ // traverse the directory and get a list of files, use that for GetHash
29+ var contents = CalculateDirectoryContents ( Path . Combine ( dotGitDirectory , "refs" ) ) ;
2830
29- return GetHash ( dotGitDirectory , lastGitRefsChangedTicks . ToString ( ) ) ;
31+ return GetHash ( contents . ToArray ( ) ) ;
32+ }
33+
34+ // based on https://msdn.microsoft.com/en-us/library/bb513869.aspx
35+ private static List < string > CalculateDirectoryContents ( string root )
36+ {
37+ var result = new List < string > ( ) ;
38+
39+ // Data structure to hold names of subfolders to be
40+ // examined for files.
41+ var dirs = new Stack < string > ( ) ;
42+
43+ if ( ! Directory . Exists ( root ) )
44+ {
45+ throw new ArgumentException ( ) ;
46+ }
47+
48+ dirs . Push ( root ) ;
49+
50+ while ( dirs . Any ( ) )
51+ {
52+ string currentDir = dirs . Pop ( ) ;
53+
54+ var di = new DirectoryInfo ( currentDir ) ;
55+ result . Add ( di . Name ) ;
56+
57+ string [ ] subDirs ;
58+ try
59+ {
60+ subDirs = Directory . GetDirectories ( currentDir ) ;
61+ }
62+ // An UnauthorizedAccessException exception will be thrown if we do not have
63+ // discovery permission on a folder or file. It may or may not be acceptable
64+ // to ignore the exception and continue enumerating the remaining files and
65+ // folders. It is also possible (but unlikely) that a DirectoryNotFound exception
66+ // will be raised. This will happen if currentDir has been deleted by
67+ // another application or thread after our call to Directory.Exists. The
68+ // choice of which exceptions to catch depends entirely on the specific task
69+ // you are intending to perform and also on how much you know with certainty
70+ // about the systems on which this code will run.
71+ catch ( UnauthorizedAccessException e )
72+ {
73+ Logger . WriteError ( e . Message ) ;
74+ continue ;
75+ }
76+ catch ( DirectoryNotFoundException e )
77+ {
78+ Logger . WriteError ( e . Message ) ;
79+ continue ;
80+ }
81+
82+ string [ ] files = null ;
83+ try
84+ {
85+ files = Directory . GetFiles ( currentDir ) ;
86+ }
87+ catch ( UnauthorizedAccessException e )
88+ {
89+ Logger . WriteError ( e . Message ) ;
90+ continue ;
91+ }
92+ catch ( DirectoryNotFoundException e )
93+ {
94+ Logger . WriteError ( e . Message ) ;
95+ continue ;
96+ }
97+
98+ foreach ( string file in files )
99+ {
100+ try
101+ {
102+ var fi = new FileInfo ( file ) ;
103+ result . Add ( fi . Name ) ;
104+ result . Add ( File . ReadAllText ( file ) ) ;
105+ }
106+ catch ( IOException e )
107+ {
108+ Logger . WriteError ( e . Message ) ;
109+ continue ;
110+ }
111+ }
112+
113+ // Push the subdirectories onto the stack for traversal.
114+ // This could also be done before handing the files.
115+ // push in reverse order
116+ for ( int i = subDirs . Length - 1 ; i >= 0 ; i -- )
117+ {
118+ dirs . Push ( subDirs [ i ] ) ;
119+ }
120+ }
121+
122+ return result ;
30123 }
31124
32125 private static string GetRepositorySnapshotHash ( GitPreparer gitPreparer )
0 commit comments