Skip to content

Commit 9fe3b19

Browse files
committed
SourceControl: centralise git clone logic
Create a helper to invoke `git clone` since we pass a few options to the invocation. This ensures that we always clone a repository with the same set of options and that we do not need to keep the various sites in sync.
1 parent 6428945 commit 9fe3b19

File tree

1 file changed

+53
-32
lines changed

1 file changed

+53
-32
lines changed

Sources/SourceControl/GitRepository.swift

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable {
9494

9595
@discardableResult
9696
private func callGit(
97-
_ args: String...,
97+
_ args: [String],
9898
environment: EnvironmentVariables = Git.environment,
9999
repository: RepositorySpecifier,
100100
failureMessage: String = "",
@@ -133,6 +133,46 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable {
133133
}
134134
}
135135

136+
@discardableResult
137+
private func callGit(
138+
_ args: String...,
139+
environment: EnvironmentVariables = Git.environment,
140+
repository: RepositorySpecifier,
141+
failureMessage: String = "",
142+
progress: FetchProgress.Handler? = nil
143+
) throws -> String {
144+
try callGit(
145+
args.map { $0 },
146+
enviornment: environment,
147+
repository: repository,
148+
failureMessage: failureMessage,
149+
progress: progress
150+
)
151+
}
152+
153+
private func clone(
154+
_ repository: RepositorySpecifier,
155+
_ origin: String,
156+
_ destination: String,
157+
_ options: [String],
158+
progress: FetchProgress.Handler? = nil
159+
) throws {
160+
let invocation: [String] = [
161+
"clone",
162+
// Enable symbolic links for Windows support.
163+
"-c", "core.symlinks=true",
164+
// Disable fsmonitor to avoid spawning a monitor process.
165+
"-c", "core.fsmonitor=false",
166+
] + options + [origin, destination]
167+
168+
try self.callGit(
169+
invocation,
170+
repository: repository,
171+
failureMessage: "Failed to clone repository \(repository.location)",
172+
progress: progress
173+
)
174+
}
175+
136176
public func fetch(
137177
repository: RepositorySpecifier,
138178
to path: Basics.AbsolutePath,
@@ -147,20 +187,11 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable {
147187
throw InternalError("\(path) already exists")
148188
}
149189

150-
// NOTE: Explicitly set `core.symlinks=true` on `git clone` to ensure that symbolic links are correctly resolved.
151-
// NOTE: Explicitly set `core.fsmonitor` on `git clone` to ensure that we do not spawn a monitor on the repository. This is
152-
// particularly important for Windows where the process can prevent future operations.
153-
try self.callGit(
154-
"clone",
155-
"-c",
156-
"core.symlinks=true",
157-
"-c",
158-
"core.fsmonitor=false",
159-
"--mirror",
190+
try self.clone(
191+
repository,
160192
repository.location.gitURL,
161193
path.pathString,
162-
repository: repository,
163-
failureMessage: "Failed to clone repository \(repository.location)",
194+
["--mirror"],
164195
progress: progressHandler
165196
)
166197
}
@@ -209,18 +240,14 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable {
209240
// For editable clones, i.e. the user is expected to directly work on them, first we create
210241
// a clone from our cache of repositories and then we replace the remote to the one originally
211242
// present in the bare repository.
212-
//
213-
// NOTE: Explicitly set `core.symlinks=true` on `git clone` to ensure that symbolic links are correctly resolved.
214-
try self.callGit(
215-
"clone",
216-
"-c",
217-
"core.symlinks=true",
218-
"--no-checkout",
243+
244+
try self.clone(
245+
repository,
219246
sourcePath.pathString,
220247
destinationPath.pathString,
221-
repository: repository,
222-
failureMessage: "Failed to clone repository \(repository.location)"
248+
["--no-checkout"]
223249
)
250+
224251
// The default name of the remote.
225252
let origin = "origin"
226253
// In destination repo remove the remote which will be pointing to the source repo.
@@ -238,18 +265,12 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable {
238265
// re-resolve such that the objects in this repository changed, we would
239266
// only ever expect to get back a revision that remains present in the
240267
// object storage.
241-
//
242-
// NOTE: Explicitly set `core.symlinks=true` on `git clone` to ensure that symbolic links are correctly resolved.
243-
try self.callGit(
244-
"clone",
245-
"-c",
246-
"core.symlinks=true",
247-
"--shared",
248-
"--no-checkout",
268+
269+
try self.clone(
270+
repository,
249271
sourcePath.pathString,
250272
destinationPath.pathString,
251-
repository: repository,
252-
failureMessage: "Failed to clone repository \(repository.location)"
273+
["--shared", "--no-checkout"]
253274
)
254275
}
255276
return try self.openWorkingCopy(at: destinationPath)

0 commit comments

Comments
 (0)