1
1
namespace GitVersion
2
2
{
3
3
using System ;
4
+ using System . Collections . Generic ;
5
+ using System . IO ;
4
6
using System . Linq ;
7
+ using System . Security . Cryptography ;
8
+ using System . Text ;
5
9
6
10
using GitVersion . Helpers ;
7
11
8
- public static class ExecuteCore
12
+ using LibGit2Sharp ;
13
+
14
+ using YamlDotNet . Serialization ;
15
+
16
+ public class ExecuteCore
9
17
{
10
- public static VersionVariables ExecuteGitVersion ( IFileSystem fileSystem , string targetUrl , string dynamicRepositoryLocation , Authentication authentication , string targetBranch , bool noFetch , string workingDirectory , string commitId )
18
+ readonly IFileSystem fileSystem ;
19
+ readonly Func < string , Func < string , VersionVariables > , VersionVariables > getOrAddFromCache ;
20
+
21
+
22
+ public ExecuteCore ( IFileSystem fileSystem , Func < string , Func < string , VersionVariables > , VersionVariables > getOrAddFromCache = null )
23
+ {
24
+ if ( fileSystem == null )
25
+ {
26
+ throw new ArgumentNullException ( "fileSystem" ) ;
27
+ }
28
+
29
+ this . getOrAddFromCache = getOrAddFromCache ;
30
+ this . fileSystem = fileSystem ;
31
+ }
32
+
33
+
34
+ public VersionVariables ExecuteGitVersion ( string targetUrl , string dynamicRepositoryLocation , Authentication authentication , string targetBranch , bool noFetch , string workingDirectory , string commitId )
35
+ {
36
+ var gitDir = Repository . Discover ( workingDirectory ) ;
37
+ using ( var repo = this . fileSystem . GetRepository ( gitDir ) )
38
+ {
39
+ // Maybe using timestamp in .git/refs directory is enough?
40
+ var ticks = this . fileSystem . GetLastDirectoryWrite ( Path . Combine ( gitDir , "refs" ) ) ;
41
+ var key = string . Format ( "{0}:{1}:{2}:{3}" , gitDir , repo . Head . CanonicalName , repo . Head . Tip . Sha , ticks ) ;
42
+
43
+ if ( this . getOrAddFromCache != null )
44
+ {
45
+ return this . getOrAddFromCache ( key , k =>
46
+ {
47
+ Logger . WriteInfo ( "Version not in memory cache. Attempting to load version from disk cache." ) ;
48
+ return LoadVersionVariablesFromDiskCache ( key , gitDir , targetUrl , dynamicRepositoryLocation , authentication , targetBranch , noFetch , workingDirectory , commitId ) ;
49
+ } ) ;
50
+ }
51
+
52
+ return LoadVersionVariablesFromDiskCache ( key , gitDir , targetUrl , dynamicRepositoryLocation , authentication , targetBranch , noFetch , workingDirectory , commitId ) ;
53
+ }
54
+ }
55
+
56
+
57
+ public bool TryGetVersion ( string directory , out VersionVariables versionVariables , bool noFetch , Authentication authentication )
58
+ {
59
+ try
60
+ {
61
+ versionVariables = ExecuteGitVersion ( null , null , authentication , null , noFetch , directory , null ) ;
62
+ return true ;
63
+ }
64
+ catch ( Exception ex )
65
+ {
66
+ Logger . WriteWarning ( "Could not determine assembly version: " + ex ) ;
67
+ versionVariables = null ;
68
+ return false ;
69
+ }
70
+ }
71
+
72
+
73
+ static string ResolveCurrentBranch ( IBuildServer buildServer , string targetBranch )
74
+ {
75
+ if ( buildServer == null )
76
+ {
77
+ return targetBranch ;
78
+ }
79
+
80
+ var currentBranch = buildServer . GetCurrentBranch ( ) ?? targetBranch ;
81
+ Logger . WriteInfo ( "Branch from build environment: " + currentBranch ) ;
82
+
83
+ return currentBranch ;
84
+ }
85
+
86
+
87
+ VersionVariables LoadVersionVariablesFromDiskCache ( string key , string gitDir , string targetUrl , string dynamicRepositoryLocation , Authentication authentication , string targetBranch , bool noFetch , string workingDirectory , string commitId )
88
+ {
89
+ using ( Logger . IndentLog ( "Loading version variables from disk cache" ) )
90
+ {
91
+ string cacheKey ;
92
+ using ( var sha1 = SHA1 . Create ( ) )
93
+ {
94
+ // Make a shorter key by hashing, to avoid having to long cache filename.
95
+ cacheKey = BitConverter . ToString ( sha1 . ComputeHash ( Encoding . UTF8 . GetBytes ( key ) ) ) . Replace ( "-" , "" ) ;
96
+ }
97
+
98
+ var cacheDir = Path . Combine ( gitDir , "gitversion_cache" ) ;
99
+ // If the cacheDir already exists, CreateDirectory just won't do anything (it won't fail). @asbjornu
100
+ this . fileSystem . CreateDirectory ( cacheDir ) ;
101
+
102
+ var cacheFileName = string . Concat ( Path . Combine ( cacheDir , cacheKey ) , ".yml" ) ;
103
+ VersionVariables vv = null ;
104
+ if ( this . fileSystem . Exists ( cacheFileName ) )
105
+ {
106
+ using ( Logger . IndentLog ( "Deserializing version variables from cache file " + cacheFileName ) )
107
+ {
108
+ try
109
+ {
110
+ vv = VersionVariables . FromFile ( cacheFileName , fileSystem ) ;
111
+ }
112
+ catch ( Exception ex )
113
+ {
114
+ Logger . WriteWarning ( "Unable to read cache file " + cacheFileName + ", deleting it." ) ;
115
+ Logger . WriteInfo ( ex . ToString ( ) ) ;
116
+ try
117
+ {
118
+ this . fileSystem . Delete ( cacheFileName ) ;
119
+ }
120
+ catch ( Exception deleteEx )
121
+ {
122
+ Logger . WriteWarning ( string . Format ( "Unable to delete corrupted version cache file {0}. Got {1} exception." , cacheFileName , deleteEx . GetType ( ) . FullName ) ) ;
123
+ }
124
+ }
125
+ }
126
+ }
127
+ else
128
+ {
129
+ Logger . WriteInfo ( "Cache file " + cacheFileName + " not found." ) ;
130
+ }
131
+
132
+ if ( vv == null )
133
+ {
134
+ vv = ExecuteInternal ( targetUrl , dynamicRepositoryLocation , authentication , targetBranch , noFetch , workingDirectory , commitId ) ;
135
+ vv . FileName = cacheFileName ;
136
+
137
+ using ( var stream = fileSystem . OpenWrite ( cacheFileName ) )
138
+ {
139
+ using ( var sw = new StreamWriter ( stream ) )
140
+ {
141
+ Dictionary < string , string > dictionary ;
142
+ using ( Logger . IndentLog ( "Creating dictionary" ) )
143
+ {
144
+ dictionary = vv . ToDictionary ( x => x . Key , x => x . Value ) ;
145
+ }
146
+
147
+ using ( Logger . IndentLog ( "Storing version variables to cache file " + cacheFileName ) )
148
+ {
149
+ var serializer = new Serializer ( ) ;
150
+ serializer . Serialize ( sw , dictionary ) ;
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ return vv ;
157
+ }
158
+ }
159
+
160
+
161
+ VersionVariables ExecuteInternal ( string targetUrl , string dynamicRepositoryLocation , Authentication authentication , string targetBranch , bool noFetch , string workingDirectory , string commitId )
11
162
{
12
163
// Normalise if we are running on build server
13
164
var gitPreparer = new GitPreparer ( targetUrl , dynamicRepositoryLocation , authentication , noFetch , workingDirectory ) ;
@@ -28,7 +179,7 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string
28
179
var versionFinder = new GitVersionFinder ( ) ;
29
180
var configuration = ConfigurationProvider . Provide ( projectRoot , fileSystem ) ;
30
181
31
- using ( var repo = fileSystem . GetRepository ( dotGitDirectory ) )
182
+ using ( var repo = this . fileSystem . GetRepository ( dotGitDirectory ) )
32
183
{
33
184
var gitVersionContext = new GitVersionContext ( repo , configuration , commitId : commitId ) ;
34
185
var semanticVersion = versionFinder . FindVersion ( gitVersionContext ) ;
@@ -37,19 +188,5 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string
37
188
38
189
return variables ;
39
190
}
40
-
41
-
42
- static string ResolveCurrentBranch ( IBuildServer buildServer , string targetBranch )
43
- {
44
- if ( buildServer == null )
45
- {
46
- return targetBranch ;
47
- }
48
-
49
- var currentBranch = buildServer . GetCurrentBranch ( ) ?? targetBranch ;
50
- Logger . WriteInfo ( "Branch from build environment: " + currentBranch ) ;
51
-
52
- return currentBranch ;
53
- }
54
191
}
55
192
}
0 commit comments