-
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-43507] Allow SCMSource and SCMNavigator subtypes to share common traits #494
Conversation
@MarkEWaite @rsandell this PR is still somewhat in progress until I complete the TODO tasks... should be mostly stable enough to review |
if (revision instanceof SCMRevisionImpl) { | ||
extensions.add(new BuildChooserSetting(new SpecificRevisionBuildChooser((SCMRevisionImpl) revision))); | ||
GitSCMBuilder<?> builder = newBuilder(head, revision); | ||
if (Util.isOverridden(AbstractGitSCMSource.class, getClass(), "getExtensions")) { |
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.
@rsandell This method is the one that needs great care and attention as we discussed previously.
The assumption is that any new subclasses cannot override these methods as they are @Restricted
thus there are either no traits (because old implementations cannot have overridden getTraits()
) or there are only traits...
Hence these methods just apply the equivalent decoration to the builder to result in the same behaviour as before...
Now I have convinced myself of the equivalence, but I really need you to probe my self-convictions ;-)
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.
Looks OK except for my worry about the DoNotUse.class
restriction.
This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation. |
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.
nothing major. mostly concerned with the suspicious hashCode()
s.
*/ | ||
@Override | ||
public int hashCode() { | ||
return 0; |
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.
timeout.hashCode()
?
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.
the fields are all mutable, thus the hashcode must be constant... should be CheckoutOption.class.hashCode()
if I am being fair to any hashsets/maps
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.
So CheckoutOption.class.hashCode()
then to be consistent with all the others.
*/ | ||
@Override | ||
public int hashCode() { | ||
return CloneOption.class.hashCode(); |
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.
Not really following the equals/hashCode contract here either.
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.
the fields are all mutable, thus the hashcode must be constant...
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.
If they where all imutable I would understand that argument.
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.
The hashcode must be consistent or the object cannot be found again. Thus you must exclude mutable fields from the hashCode calculation.
If all fields are mutable then no fields may be used to calculate the hashCode.
Since we expect these to end up in collections with their sibling class implementations and we only ever have at most one impl of a given type, we just give each impl a different constant hashCode and all is right with the world
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.
It would even be acceptable if they had the same hashCode, wouldn't it? They would collide in the hash buckets, but that would (at most) have a performance impact, not a functional impact.
*/ | ||
@Override | ||
public int hashCode() { | ||
return LocalBranch.class.hashCode(); |
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.
dito
*/ | ||
@Override | ||
public int hashCode() { | ||
return SubmoduleOption.class.hashCode(); |
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.
dito
try { | ||
hash = client.revParse(context.remoteName() + "/" + revision).name(); | ||
} catch (GitException x2) { | ||
listener.getLogger().println(x.getMessage()); |
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.
So in case of the first exception x
, but not the second x2
, there won't be anything printed to the log?
RefSpecsSCMSourceTrait trait = asRefSpecsSCMSourceTrait(rawRefSpecs, remoteName); | ||
if (trait != null) { | ||
traits.add(trait); | ||
} |
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.
should probably set most fields to null after the conversion to potentially be able to collect some garbage.
@@ -188,43 +344,55 @@ public String getRemote() { | |||
return remote; | |||
} | |||
|
|||
@Override | |||
public String getRemoteName() { |
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.
hard to see in this diff if all old removed signatures are removed or just moved.
*/ | ||
@Override | ||
public String getDisplayName() { | ||
return "Use commit author in changelog"; |
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.
I18n? Some display names might be reusable from the extensions.
public String getHelpFile() { | ||
String primary = super.getHelpFile(); | ||
return primary == null ? getExtensionDescriptor().getHelpFile() : primary; | ||
} |
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.
not the tooltip? :-p
~ THE SOFTWARE. | ||
--> | ||
|
||
<div> |
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.
shouldn't this just be moved to the trait?
…nd toString implementation requirements
…aseline version of Jenkins core
… by GitSCMSource should honour refspecs on clone and not fetch tags
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.
🐝
*/ | ||
@Override | ||
public int hashCode() { | ||
return 0; |
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.
So CheckoutOption.class.hashCode()
then to be consistent with all the others.
if (refSpecs.isEmpty()) { | ||
return ""; | ||
} | ||
if (refSpecs.size() == 1) { |
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.
StringUtils.join(refSpecs, ' ');
*/ | ||
@Override | ||
public String getDisplayName() { | ||
return "Advanced checkout behaviours"; |
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.
I18n
*/ | ||
@Override | ||
public String getDisplayName() { | ||
return "Ref Spec"; |
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.
I18n?
assertThat(instance.gitTool(), is("git")); | ||
GitSCM scm = instance.build(); | ||
assertThat(scm.getBrowser(), is(nullValue())); | ||
assertThat(scm.getUserRemoteConfigs(), contains(allOf( |
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.
Seems very excessive to assert on these all the time, since if there is a problem with it it will get reported on "unrelated" tests.
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.
Started, but not finished the review. No issues found to date
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
return o instanceof AuthorInChangelog; |
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.
Doesn't the check:
getClass() != o.getClass()
guarantee that o is an instanceof AuthorInChangelog? If so, isn't this more readily expressed as "return true"? Or is this worrying about the risk of a class which might inherit from this class and fail to override the equals method?
I think it is correct that every instance of AuthorInChangelog is equal to every other instance of AuthorInChangelog, since the AuthorInChangelog class is being used as a boolean. If AuthorInChangelog is enabled, then the author should be used rather than the committer when displaying changelogs.
@Override | ||
public void decorateFetchCommand(GitSCM scm, GitClient git, TaskListener listener, FetchCommand cmd) throws IOException, InterruptedException, GitException { | ||
cmd.shallow(shallow); | ||
if (shallow && depth > 1) { | ||
cmd.depth(depth); | ||
cmd.depth(depth); |
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.
Leading tab before a space?
*/ | ||
@Override | ||
public int hashCode() { | ||
return CloneOption.class.hashCode(); |
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.
It would even be acceptable if they had the same hashCode, wouldn't it? They would collide in the hash buckets, but that would (at most) have a performance impact, not a functional impact.
…on for JENKINS-33445
Ok, merging to master in order to cut beta... any required changes will be in follow-up PRs |
https://github.com/jenkinsci/git-plugin/tree/stable-3.3.x was cut from master pre-merge in case any changes are needed to be released on the 3.3.x line |
Downstream of jenkinsci/scm-api-plugin#36
See JENKINS-43507
@reviewbybees
Todo