- 
                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.