1
+ namespace GitTools . Git
2
+ {
3
+ using System ;
4
+ using System . IO ;
5
+ using System . Linq ;
6
+ using LibGit2Sharp ;
7
+ using Logging ;
8
+
9
+ public class GitPreparer
10
+ {
11
+ private static readonly ILog Log = LogProvider . GetCurrentClassLogger ( ) ;
12
+
13
+ string targetUrl ;
14
+ string dynamicRepositoryLocation ;
15
+ AuthenticationInfo authentication ;
16
+ bool noFetch ;
17
+ string targetPath ;
18
+
19
+ public GitPreparer ( string targetUrl , string dynamicRepositoryLocation , AuthenticationInfo authentication , bool noFetch , string targetPath )
20
+ {
21
+ this . targetUrl = targetUrl ;
22
+ this . dynamicRepositoryLocation = dynamicRepositoryLocation ;
23
+ this . authentication = authentication ?? new AuthenticationInfo ( ) ;
24
+ this . noFetch = noFetch ;
25
+ this . targetPath = targetPath ;
26
+ }
27
+
28
+ public bool IsDynamicGitRepository
29
+ {
30
+ get { return ! string . IsNullOrWhiteSpace ( DynamicGitRepositoryPath ) ; }
31
+ }
32
+
33
+ public string DynamicGitRepositoryPath { get ; private set ; }
34
+
35
+ public void Initialise ( bool normaliseGitDirectory , string currentBranch )
36
+ {
37
+ if ( string . IsNullOrWhiteSpace ( targetUrl ) )
38
+ {
39
+ if ( normaliseGitDirectory )
40
+ {
41
+ GitHelper . NormalizeGitDirectory ( GetDotGitDirectory ( ) , authentication , noFetch , currentBranch ) ;
42
+ }
43
+ return ;
44
+ }
45
+
46
+ var tempRepositoryPath = CalculateTemporaryRepositoryPath ( targetUrl , dynamicRepositoryLocation ) ;
47
+
48
+ DynamicGitRepositoryPath = CreateDynamicRepository ( tempRepositoryPath , authentication , targetUrl , currentBranch , noFetch ) ;
49
+ }
50
+
51
+ static string CalculateTemporaryRepositoryPath ( string targetUrl , string dynamicRepositoryLocation )
52
+ {
53
+ var userTemp = dynamicRepositoryLocation ?? Path . GetTempPath ( ) ;
54
+ var repositoryName = targetUrl . Split ( '/' , '\\ ' ) . Last ( ) . Replace ( ".git" , string . Empty ) ;
55
+ var possiblePath = Path . Combine ( userTemp , repositoryName ) ;
56
+
57
+ // Verify that the existing directory is ok for us to use
58
+ if ( Directory . Exists ( possiblePath ) )
59
+ {
60
+ if ( ! GitRepoHasMatchingRemote ( possiblePath , targetUrl ) )
61
+ {
62
+ var i = 1 ;
63
+ var originalPath = possiblePath ;
64
+ bool possiblePathExists ;
65
+ do
66
+ {
67
+ possiblePath = string . Concat ( originalPath , "_" , i ++ . ToString ( ) ) ;
68
+ possiblePathExists = Directory . Exists ( possiblePath ) ;
69
+ } while ( possiblePathExists && ! GitRepoHasMatchingRemote ( possiblePath , targetUrl ) ) ;
70
+ }
71
+ }
72
+
73
+ return possiblePath ;
74
+ }
75
+
76
+ static bool GitRepoHasMatchingRemote ( string possiblePath , string targetUrl )
77
+ {
78
+ try
79
+ {
80
+ using ( var repository = new Repository ( possiblePath ) )
81
+ {
82
+ return repository . Network . Remotes . Any ( r => r . Url == targetUrl ) ;
83
+ }
84
+ }
85
+ catch ( Exception )
86
+ {
87
+ return false ;
88
+ }
89
+ }
90
+
91
+ public string GetDotGitDirectory ( )
92
+ {
93
+ if ( IsDynamicGitRepository )
94
+ {
95
+ return DynamicGitRepositoryPath ;
96
+ }
97
+
98
+ return GitDirFinder . TreeWalkForDotGitDir ( targetPath ) ;
99
+ }
100
+
101
+ public string GetProjectRootDirectory ( )
102
+ {
103
+ if ( IsDynamicGitRepository )
104
+ {
105
+ return targetPath ;
106
+ }
107
+
108
+ return Directory . GetParent ( GitDirFinder . TreeWalkForDotGitDir ( targetPath ) ) . FullName ;
109
+ }
110
+
111
+ static string CreateDynamicRepository ( string targetPath , AuthenticationInfo authentication , string repositoryUrl , string targetBranch , bool noFetch )
112
+ {
113
+ if ( string . IsNullOrWhiteSpace ( targetBranch ) )
114
+ {
115
+ throw new Exception ( "Dynamic Git repositories must have a target branch (/b)" ) ;
116
+ }
117
+
118
+ Log . Info ( string . Format ( "Creating dynamic repository at '{0}'" , targetPath ) ) ;
119
+
120
+ var gitDirectory = Path . Combine ( targetPath , ".git" ) ;
121
+ if ( Directory . Exists ( targetPath ) )
122
+ {
123
+ Log . Info ( "Git repository already exists" ) ;
124
+ GitHelper . NormalizeGitDirectory ( gitDirectory , authentication , noFetch , targetBranch ) ;
125
+
126
+ return gitDirectory ;
127
+ }
128
+
129
+ CloneRepository ( repositoryUrl , gitDirectory , authentication ) ;
130
+
131
+ // Normalize (download branches) before using the branch
132
+ GitHelper . NormalizeGitDirectory ( gitDirectory , authentication , noFetch , targetBranch ) ;
133
+
134
+ return gitDirectory ;
135
+ }
136
+
137
+ private static void CloneRepository ( string repositoryUrl , string gitDirectory , AuthenticationInfo authentication )
138
+ {
139
+ Credentials credentials = null ;
140
+ if ( ! string . IsNullOrWhiteSpace ( authentication . Username ) && ! string . IsNullOrWhiteSpace ( authentication . Password ) )
141
+ {
142
+ Log . Info ( string . Format ( "Setting up credentials using name '{0}'" , authentication . Username ) ) ;
143
+
144
+ credentials = new UsernamePasswordCredentials
145
+ {
146
+ Username = authentication . Username ,
147
+ Password = authentication . Password
148
+ } ;
149
+ }
150
+
151
+ Log . Info ( string . Format ( "Retrieving git info from url '{0}'" , repositoryUrl ) ) ;
152
+
153
+ try
154
+ {
155
+ Repository . Clone ( repositoryUrl , gitDirectory ,
156
+ new CloneOptions
157
+ {
158
+ Checkout = false ,
159
+ CredentialsProvider = ( url , usernameFromUrl , types ) => credentials
160
+ } ) ;
161
+ }
162
+ catch ( LibGit2SharpException ex )
163
+ {
164
+ var message = ex . Message ;
165
+ if ( message . Contains ( "401" ) )
166
+ {
167
+ throw new Exception ( "Unauthorised: Incorrect username/password" ) ;
168
+ }
169
+ if ( message . Contains ( "403" ) )
170
+ {
171
+ throw new Exception ( "Forbidden: Possbily Incorrect username/password" ) ;
172
+ }
173
+ if ( message . Contains ( "404" ) )
174
+ {
175
+ throw new Exception ( "Not found: The repository was not found" ) ;
176
+ }
177
+
178
+ throw new Exception ( "There was an unknown problem with the Git repository you provided" ) ;
179
+ }
180
+ }
181
+ }
182
+ }
0 commit comments