-
Notifications
You must be signed in to change notification settings - Fork 399
[JENKINS-64383] combined refrepo became our bottleneck, support a fanout location too #644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 121 commits
8f5ec33
022bbc6
6210adb
06d4859
b5a6a7b
f90bdca
e09eff1
17010ca
72a4a05
c6c010f
bbedefd
5306163
bc7e198
3ff19df
a509386
603e390
66e23a1
5af4400
509c5ec
0b0fcbf
6a9c79d
2641971
c10231c
2016719
71c0850
ab04ae7
179f5c1
7c0ad4f
ead03a6
5fde3c9
6c7374c
a2cf84f
823bd0f
0e5e0cd
172e40e
d6cebe8
864e34f
55fda14
3e81723
ff65341
122746f
bf978ee
aacc0cd
1a8306a
769a2d4
654362a
5b6ff6d
8d8514c
925eaba
a103bdd
aaaef9c
a77dab9
d664eb3
e29d947
1816632
8b693fd
e49b985
ab29c68
66798fd
776a249
094de4d
d30de21
7ed0f0f
14cf345
2b61767
1c9a8f5
a29b00c
25bef67
39dd9b4
c349b25
6a7bb18
f475606
2ddd7df
721d791
69f5b59
9c48cb6
f465258
f6e756a
ce1827e
c5e863f
d0bf23c
0b761da
6046f4b
3f7b4e4
61a7d0b
b91e00b
65684f3
0c99c95
327cb48
45d268c
0413d95
fad3727
d37fe49
6afacda
b278523
4468443
0edcc0c
0767c2a
03b3056
fd88900
d72999b
f1f478a
91ed630
de98cd1
aa9eaad
82a43eb
23745a8
f51e60f
a5fdbd3
4341cd2
4cd45c8
fd293d7
c45cedd
be57864
8f843d4
4ee6935
e726d40
558d076
4402820
5d97abe
4222f4e
63ca351
2544b99
059f7a2
7c28d4d
c882050
9863085
8334390
eeb47b4
9f162aa
d3a6d56
6840c75
d8ddcdb
896c2c6
62355d5
2c10b59
59e7474
4e1f3ab
f844f23
43c38ba
65b55c5
9da15fa
1f379a7
cedfd7f
b2d7fef
9dc373e
d2fd099
286fd39
ce14ece
86c2933
2ff86b7
0f8e120
c439d46
d3e17d9
05dbf78
f95cbe3
2868f17
8cd7e77
b5dbfdb
37196d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -345,6 +345,12 @@ public GitClient subGit(String subdir) { | |
| return new CliGitAPIImpl(gitExe, new File(workspace, subdir), listener, environment); | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public GitClient newGit(String somedir) { | ||
| return new CliGitAPIImpl(gitExe, new File(somedir), listener, environment); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize an empty repository for further git operations. | ||
| * | ||
|
|
@@ -812,31 +818,51 @@ public void execute() throws GitException, InterruptedException { | |
| } | ||
|
|
||
| if (reference != null && !reference.isEmpty()) { | ||
| File referencePath = new File(reference); | ||
| if (!referencePath.exists()) | ||
| listener.getLogger().println("[WARNING] Reference path does not exist: " + reference); | ||
| else if (!referencePath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path is not a directory: " + reference); | ||
| else { | ||
| // reference path can either be a normal or a base repository | ||
| File objectsPath = new File(referencePath, ".git/objects"); | ||
| if (!objectsPath.isDirectory()) { | ||
| // reference path is bare repo | ||
| objectsPath = new File(referencePath, "objects"); | ||
| if (isParameterizedReferenceRepository(reference)) { | ||
| // LegacyCompatibleGitAPIImpl.java has a logging trace, but not into build console via listener | ||
| listener.getLogger().println("[INFO] The git reference repository path '" + | ||
| reference + "' is parameterized, it may take a few git queries logged " + | ||
| "below to resolve it into a particular directory name"); | ||
| } | ||
| File referencePath = findParameterizedReferenceRepository(reference, url); | ||
| if (referencePath == null) { | ||
| listener.getLogger().println("[ERROR] Could not make File object from reference path, skipping its use: " + reference); | ||
| } else { | ||
| if (!referencePath.getPath().equals(reference)) { | ||
| // Note: both these logs are needed, they are used in selftest | ||
| String msg = "Parameterized reference path "; | ||
| msg += "'" + reference + "'"; | ||
| msg += " replaced with: "; | ||
| msg += "'" + referencePath.getPath() + "'"; | ||
| if (referencePath.exists()) { | ||
| listener.getLogger().println("[WARNING] " + msg); | ||
| } else { | ||
| listener.getLogger().println("[WARNING] " + msg + " does not exist"); | ||
| } | ||
| reference = referencePath.getPath(); | ||
| } | ||
| if (!objectsPath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path does not contain an objects directory (not a git repo?): " + objectsPath); | ||
|
|
||
| if (!referencePath.exists()) | ||
| listener.getLogger().println("[WARNING] Reference path does not exist: " + reference); | ||
| else if (!referencePath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path is not a directory: " + reference); | ||
| else { | ||
| File alternates = new File(workspace, ".git/objects/info/alternates"); | ||
| try (PrintWriter w = new PrintWriter(alternates, Charset.defaultCharset().toString())) { | ||
| String absoluteReference = objectsPath.getAbsolutePath().replace('\\', '/'); | ||
| listener.getLogger().println("Using reference repository: " + reference); | ||
| // git implementations on windows also use | ||
| w.print(absoluteReference); | ||
| } catch (UnsupportedEncodingException ex) { | ||
| listener.error("Default character set is an unsupported encoding"); | ||
| } catch (FileNotFoundException e) { | ||
| listener.error("Failed to setup reference"); | ||
| File objectsPath = getObjectsFile(referencePath); | ||
| if (objectsPath == null || !objectsPath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path does not contain an objects directory (not a git repo?): " + objectsPath); | ||
| else { | ||
| // Go behind git's back to write a meta file in new workspace | ||
| File alternates = new File(workspace, ".git/objects/info/alternates"); | ||
| try (PrintWriter w = new PrintWriter(alternates, Charset.defaultCharset().toString())) { | ||
| String absoluteReference = objectsPath.getAbsolutePath().replace('\\', '/'); | ||
| listener.getLogger().println("Using reference repository: " + reference); | ||
| // git implementations on windows also use | ||
| w.print(absoluteReference); | ||
| } catch (UnsupportedEncodingException ex) { | ||
| listener.error("Default character set is an unsupported encoding"); | ||
| } catch (FileNotFoundException e) { | ||
| listener.error("Failed to setup reference"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1428,13 +1454,15 @@ public void execute() throws GitException, InterruptedException { | |
| } | ||
| } | ||
| if ((ref != null) && !ref.isEmpty()) { | ||
| File referencePath = new File(ref); | ||
| if (!referencePath.exists()) | ||
| listener.getLogger().println("[WARNING] Reference path does not exist: " + ref); | ||
| else if (!referencePath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path is not a directory: " + ref); | ||
| else | ||
| args.add("--reference", ref); | ||
| if (!isParameterizedReferenceRepository(ref)) { | ||
| File referencePath = new File(ref); | ||
| if (!referencePath.exists()) | ||
| listener.getLogger().println("[WARNING] Reference path does not exist: " + ref); | ||
| else if (!referencePath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path is not a directory: " + ref); | ||
| else | ||
| args.add("--reference", ref); | ||
| } // else handled below in per-module loop | ||
| } | ||
| if (shallow) { | ||
| if (depth == null) { | ||
|
|
@@ -1484,9 +1512,34 @@ else if (!referencePath.isDirectory()) | |
| listener.error("Invalid repository for " + sModuleName); | ||
| throw new GitException("Invalid repository for " + sModuleName); | ||
| } | ||
| String strURIish = null; | ||
| if (urIish != null) { | ||
| strURIish = urIish.toPrivateString(); | ||
| } | ||
|
|
||
| if (isParameterizedReferenceRepository(ref)) { | ||
| File referencePath = findParameterizedReferenceRepository(ref, strURIish); | ||
| if (referencePath == null) { | ||
| listener.getLogger().println("[ERROR] Could not make File object from reference path, skipping its use: " + ref); | ||
| } else { | ||
| String expRef = null; | ||
| if (referencePath.getPath().equals(ref)) { | ||
| expRef = ref; | ||
| } else { | ||
| expRef = referencePath.getPath(); | ||
| expRef += " (expanded from " + ref + ")"; | ||
| } | ||
| if (!referencePath.exists()) | ||
| listener.getLogger().println("[WARNING] Reference path does not exist: " + expRef); | ||
| else if (!referencePath.isDirectory()) | ||
| listener.getLogger().println("[WARNING] Reference path is not a directory: " + expRef); | ||
| else | ||
| args.add("--reference", referencePath.getPath()); | ||
| } | ||
| } | ||
|
|
||
| // Find credentials for this URL | ||
| StandardCredentials cred = credentials.get(urIish.toPrivateString()); | ||
| StandardCredentials cred = credentials.get(strURIish); | ||
| if (parentCredentials) { | ||
| String parentUrl = getRemoteUrl(getDefaultRemote()); | ||
| URIish parentUri = null; | ||
|
|
@@ -1594,6 +1647,60 @@ public void setSubmoduleUrl(String name, String url) throws GitException, Interr | |
| return StringUtils.trim(firstLine(result)); | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public @CheckForNull Map<String, String> getRemoteUrls() throws GitException, InterruptedException { | ||
| String result = launchCommand( "config", "--local", "--list" ); | ||
| Map<String, String> uriNames = new HashMap<>(); | ||
| for (String line : result.split("\\R+")) { | ||
| line = StringUtils.trim(line); | ||
| if (!line.startsWith("remote.") || !line.contains(".url=")) { | ||
| continue; | ||
| } | ||
|
|
||
| String remoteName = StringUtils.substringBetween(line, "remote.", ".url="); | ||
| String remoteUri = StringUtils.substringAfter(line, ".url="); | ||
|
|
||
| // If uri String values end up identical, Map only stores one entry | ||
| uriNames.put(remoteUri, remoteName); | ||
|
|
||
| try { | ||
| URI u = new URI(remoteUri); | ||
| uriNames.put(u.toASCIIString(), remoteName); | ||
| URI uSafe = new URI(u.getScheme(), u.getHost(), u.getPath(), u.getFragment()); | ||
| uriNames.put(uSafe.toString(), remoteName); | ||
| uriNames.put(uSafe.toASCIIString(), remoteName); | ||
| } catch (URISyntaxException ue) {} // ignore, move along | ||
| } | ||
| return uriNames; | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public @CheckForNull Map<String, String> getRemotePushUrls() throws GitException, InterruptedException { | ||
| String result = launchCommand( "config", "--local", "--list" ); | ||
|
||
| Map<String, String> uriNames = new HashMap<>(); | ||
| for (String line : result.split("\\R+")) { | ||
| line = StringUtils.trim(line); | ||
| if (!line.startsWith("remote.") || !line.contains(".pushurl=")) { | ||
| continue; | ||
| } | ||
|
|
||
| String remoteName = StringUtils.substringBetween(line, "remote.", ".pushurl="); | ||
| String remoteUri = StringUtils.substringAfter(line, ".pushurl="); | ||
| uriNames.put(remoteUri, remoteName); | ||
|
|
||
| try { | ||
| URI u = new URI(remoteUri); | ||
| uriNames.put(u.toASCIIString(), remoteName); | ||
| URI uSafe = new URI(u.getScheme(), u.getHost(), u.getPath(), u.getFragment()); | ||
| uriNames.put(uSafe.toString(), remoteName); | ||
| uriNames.put(uSafe.toASCIIString(), remoteName); | ||
| } catch (URISyntaxException ue) {} // ignore, move along | ||
| } | ||
| return uriNames; | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public void setRemoteUrl(String name, String url) throws GitException, InterruptedException { | ||
|
|
@@ -2693,7 +2800,12 @@ private String launchCommandIn(ArgumentListBuilder args, File workDir, EnvVars e | |
| } | ||
|
|
||
| if (status != 0) { | ||
| throw new GitException("Command \"" + command + "\" returned status code " + status + ":\nstdout: " + stdout + "\nstderr: "+ stderr); | ||
| if (workDir == null) | ||
| workDir = java.nio.file.Paths.get(".").toAbsolutePath().normalize().toFile(); | ||
| throw new GitException("Command \"" + command + | ||
| "\" executed in workdir \"" + workDir.toString() + | ||
| "\" returned status code " + status + | ||
| ":\nstdout: " + stdout + "\nstderr: " + stderr); | ||
| } | ||
|
|
||
| return stdout; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There don't appear to be any tests for this new method. The method was not called from the modified tests in GitClientCloneTest.
I'd like tests that confirm the method is well-behaved. There need to be tests of the method before it is merged.
The tests could be created in GitClientTest or in a new test class created based on GitClientTest. Because GitClientTest is parameterized and iterates over
git,jgit, andjgitapache, it increases the coverage without dramatically increasing the amount of test code.