-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[JENKINS-49757] Remove redundant fetch #904
Changes from 27 commits
8d58567
23158ea
9b25935
2cf858e
11a87d4
5d94f2e
1cfb539
e6ac2ed
eaded93
21ead1e
67ced0e
995d803
ae036cc
82ffbbf
3bc0059
57ab0d0
05daa5e
d3a1e22
36e3e7d
deb1b78
c4c47cb
e8d1bca
b54faeb
79cf010
a38f1e2
1be3697
15e2f52
7957017
f2fecc8
a7685db
1623253
09726f1
c7b7ec6
f7b77e6
534818a
c2e097d
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 |
---|---|---|
|
@@ -39,6 +39,7 @@ | |
import hudson.plugins.git.extensions.impl.LocalBranch; | ||
import hudson.plugins.git.extensions.impl.RelativeTargetDirectory; | ||
import hudson.plugins.git.extensions.impl.PreBuildMerge; | ||
import hudson.plugins.git.extensions.impl.CloneOption; | ||
import hudson.plugins.git.opt.PreBuildMergeOptions; | ||
import hudson.plugins.git.util.Build; | ||
import hudson.plugins.git.util.*; | ||
|
@@ -110,7 +111,6 @@ | |
import hudson.plugins.git.browser.GithubWeb; | ||
import static hudson.scm.PollingResult.*; | ||
import hudson.Util; | ||
import hudson.plugins.git.extensions.impl.ScmName; | ||
import hudson.util.LogTaskListener; | ||
import hudson.util.ReflectionUtils; | ||
import java.util.Map.Entry; | ||
|
@@ -1111,6 +1111,7 @@ public EnvVars getEnvironment() { | |
private void retrieveChanges(Run build, GitClient git, TaskListener listener) throws IOException, InterruptedException { | ||
final PrintStream log = listener.getLogger(); | ||
|
||
boolean removeRedundantFetch = false; | ||
List<RemoteConfig> repos = getParamExpandedRepos(build, listener); | ||
if (repos.isEmpty()) return; // defensive check even though this is an invalid configuration | ||
|
||
|
@@ -1130,13 +1131,20 @@ private void retrieveChanges(Run build, GitClient git, TaskListener listener) th | |
ext.decorateCloneCommand(this, build, git, listener, cmd); | ||
} | ||
cmd.execute(); | ||
// determine if second fetch is required | ||
CloneOption option = extensions.get(CloneOption.class); | ||
removeRedundantFetch = determineRedundantFetch(option, rc); | ||
} catch (GitException ex) { | ||
ex.printStackTrace(listener.error("Error cloning remote repo '" + rc.getName() + "'")); | ||
throw new AbortException("Error cloning remote repo '" + rc.getName() + "'"); | ||
} | ||
} | ||
|
||
for (RemoteConfig remoteRepository : repos) { | ||
if (remoteRepository.equals(repos.get(0)) && removeRedundantFetch){ | ||
log.println("Avoid second fetch"); | ||
continue; | ||
} | ||
try { | ||
fetchFrom(git, build, listener, remoteRepository); | ||
} catch (GitException ex) { | ||
|
@@ -1148,6 +1156,30 @@ private void retrieveChanges(Run build, GitClient git, TaskListener listener) th | |
} | ||
} | ||
|
||
private boolean determineRedundantFetch(CloneOption option, RemoteConfig rc) { | ||
List<RefSpec> initialFetchRefSpecs = rc.getFetchRefSpecs(); | ||
boolean isDefaultRefspec = true; // default refspec is any refspec with "refs/heads/" mapping | ||
boolean removeSecondFetch = true; | ||
if (initialFetchRefSpecs != null) { | ||
for (RefSpec ref : initialFetchRefSpecs) { | ||
if (!ref.toString().contains("refs/heads")) { | ||
isDefaultRefspec = false; // if refspec is not of default type, preserve second fetch | ||
} | ||
} | ||
if (option == null) { | ||
removeSecondFetch = isDefaultRefspec; | ||
} else { | ||
if (!option.isHonorRefspec()) { | ||
removeSecondFetch = isDefaultRefspec; | ||
} else { | ||
removeSecondFetch = true; // avoid second fetch call if honor refspec is enabled | ||
} | ||
} | ||
} | ||
// if initial fetch refspec contains "refs/heads/*" (default refspec), ignore the second fetch call | ||
return removeSecondFetch; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a test that passed in a null refspec but the UserRemoteConfig constructor converts nulls to empty strings. I think that is unreachable code due to the UserRemoteConfig use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to my assumptions, the need to add the null check was to check for empty refspecs, as Mark as correctly pointed out, the If the UserRemoteConfig was not fixing empty refspecs, the logic presented by me would gladly pass |
||
} | ||
|
||
@Override | ||
public void checkout(Run<?, ?> build, Launcher launcher, FilePath workspace, TaskListener listener, File changelogFile, SCMRevisionState baseline) | ||
throws IOException, InterruptedException { | ||
|
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.
This if clause didn't help me to see clearer what you meant. While having a "!" in an
if
clause is perfectly fine, the "!" in theif-else
might cause confusion. I would have expectedwhile this piece of code is
My personal preference is to have the first approach in terms of readability. But it's just a matter of personal taste, so take this advice as it is, just an advice.
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.
This is a great suggestion @fcojfernandez. I have added this in c2e097d.