Merge branch 'stable-2.9' into stable-2.10
* stable-2.9:
Consume API version 2.9
Merge made by the 'ours' strategy.
Change-Id: Idd0d6ee249b61a2ac213c98d1d45426eb1f21ab6
diff --git a/its-base/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
similarity index 100%
rename from its-base/.settings/org.eclipse.core.resources.prefs
rename to .settings/org.eclipse.core.resources.prefs
diff --git a/its-base/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs
similarity index 100%
rename from its-base/.settings/org.eclipse.core.runtime.prefs
rename to .settings/org.eclipse.core.runtime.prefs
diff --git a/its-base/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
similarity index 100%
rename from its-base/.settings/org.eclipse.jdt.core.prefs
rename to .settings/org.eclipse.jdt.core.prefs
diff --git a/its-base/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
similarity index 100%
rename from its-base/.settings/org.eclipse.jdt.ui.prefs
rename to .settings/org.eclipse.jdt.ui.prefs
diff --git a/BUCK b/BUCK
new file mode 100644
index 0000000..c5d6009
--- /dev/null
+++ b/BUCK
@@ -0,0 +1,61 @@
+include_defs('//bucklets/gerrit_plugin.bucklet')
+
+DEPS = [
+ '//lib/commons:lang',
+ '//lib:guava',
+ '//lib/guice:guice',
+ '//lib/jgit:jgit',
+ '//lib/log:api',
+ '//lib:parboiled-core',
+ '//lib:velocity',
+]
+
+gerrit_plugin(
+ name = 'its-base',
+ srcs = glob(['src/main/java/**/*.java']),
+ resources = glob(['src/main/resources/**/*']),
+ provided_deps = DEPS,
+)
+
+TEST_UTIL_SRC = glob(['src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/**/*.java'])
+
+java_library(
+ name = 'its-base_tests-utils',
+ srcs = TEST_UTIL_SRC,
+ deps = DEPS + [
+ '//lib/easymock:easymock',
+ '//lib/log:impl_log4j',
+ '//lib/log:log4j',
+ '//lib:junit',
+ '//lib/powermock:powermock-api-easymock',
+ '//lib/powermock:powermock-api-support',
+ '//lib/powermock:powermock-core',
+ '//lib/powermock:powermock-module-junit4',
+ '//lib/powermock:powermock-module-junit4-common',
+ ],
+)
+
+java_test(
+ name = 'its-base_tests',
+ srcs = glob(
+ ['src/test/java/**/*.java'],
+ excludes = TEST_UTIL_SRC
+ ),
+ labels = ['its-base'],
+ source_under_test = [':its-base__plugin'],
+ deps = DEPS + [
+ ':its-base__plugin',
+ ':its-base_tests-utils',
+ '//gerrit-plugin-api:lib',
+ '//lib:gwtorm',
+ '//lib/easymock:easymock',
+ '//lib/log:impl_log4j',
+ '//lib/log:log4j',
+ '//lib:junit',
+ '//lib/powermock:powermock-api-easymock',
+ '//lib/powermock:powermock-api-support',
+ '//lib/powermock:powermock-core',
+ '//lib/powermock:powermock-module-junit4',
+ '//lib/powermock:powermock-module-junit4-common',
+ ],
+)
diff --git a/its-base/pom.xml b/its-base/pom.xml
deleted file mode 100644
index 381789b..0000000
--- a/its-base/pom.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
- xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>com.googlesource.gerrit.plugins.its</groupId>
- <artifactId>its-base-parent</artifactId>
- <version>2.9</version>
- </parent>
- <artifactId>its-base</artifactId>
- <name>Gerrit Code Review - Commit validation and Workflow</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <dependency>
- <groupId>com.google.gerrit</groupId>
- <artifactId>gerrit-plugin-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.velocity</groupId>
- <artifactId>velocity</artifactId>
- <version>${velocityVersion}</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>${slf4jVersion}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.easymock</groupId>
- <artifactId>easymock</artifactId>
- <version>${easymockVersion}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-junit4</artifactId>
- <version>${powermockVersion}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-easymock</artifactId>
- <version>${powermockVersion}</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
-</project>
diff --git a/its-base/src/main/resources/Documentation/config.md b/its-base/src/main/resources/Documentation/config.md
deleted file mode 100644
index 81f7660..0000000
--- a/its-base/src/main/resources/Documentation/config.md
+++ /dev/null
@@ -1,641 +0,0 @@
-hooks-its
-=========
-
-link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/hooks-its['hooks-its']
-is by itself not a real plugin, but the common parent project for issue tracking
-system (ITS) plugins for Gerrit, such as
-link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/hooks-bugzilla['hooks-bugzilla'],
-link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/hooks-jira['hooks-jira']
-or link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/hooks-rtc['hooks-rtc'].
-
-[[config]]
-Common configuration
---------------------
-
-The base functionality for 'hooks-its' based plugins is configured via
-git config files in the site's `etc/its` directory. Footnote:[The
-<<config-legacy,legacy configuration>> directly in `etc/gerrit.config`
-still works, but upgrading to this xref:config[new, more flexible
-approach] is strongly recommended.].
-
-Setting up which event in Gerrit (E.g.: “Change Merged”, or “User
-‘John Doe’ voted ‘+2’ for ‘Code-Review’ on a change”) should trigger
-which action on the ITS (e.g.: “Set issue's status to ‘Resolved’”) is
-configured through a xref:config-rule-base[rule base] in
-`etc/its/action.config`.
-
-It can be configured per project whether the issue tracker
-integration is enabled or not. To enable the issue tracker integration
-for a project the project must have the following entry in its
-`project.config` file in the `refs/meta/config` branch:
-
-```
- [plugin "<its-name>"]
- enabled = true
-```
-
-If `plugin.<its-name>.enabled` is not specified in the `project.config`
-file the value is inherited from the parent project. If it is not
-set on any parent project the issue integration is disabled for this
-project.
-
-By setting `plugin.<its-name>.enabled` to true in the `project.config`
-of the `All-Projects` project the issue tracker integration can be
-enabled by default for all projects. During the initialization of the
-plugin you are asked if the issue integration should be enabled by
-default for all projects and if yes this setting in the
-`project.config` of the `All-Projects` project is done automatically.
-
-With this it is possible to support integration with multiple
-issue tracker systems on a server. E.g. a project can choose if it
-wants to enable integration with Jira or with Bugzilla.
-
-If child projects must not be allowed to disable the issue tracker
-system integration a project can enforce the issue tracker system
-integration for all child projects by setting
-`plugin.<its-name>.enabled` to `enforced`.
-
-The issue tracker system integration can be limited to specific
-branches by setting `plugin.<its-name>.branch`. The branches may be
-configured using explicit branch names, ref patterns, or regular
-expressions. Multiple branches may be specified.
-
-E.g. to limit the issue tracker system integration to the `master`
-branch and all stable branches the following could be configured:
-
-```
- [plugin "<its-name>"]
- enabled = true
- branch = refs/heads/master
- branch = ^refs/heads/stable-.*
-```
-
-
-[[config-rule-base]]
-Rule base for Actions
-~~~~~~~~~~~~~~~~~~~~~
-
-In this part we describe how to specify which events in Gerrit (E.g.:
-“Change Merged”, or “User ‘John Doe’ voted ‘+2’ for ‘Code-Review’ on a
-change”) trigger which actions (e.g.: “Set issue's status to
-‘Resolved’”) on the ITS.
-
-Actions on the ITS and conditions for the action to take place are
-configured through the rule base in `etc/its/actions.config` in the
-site directory. The rule base is a git config file, and may contain an
-arbitrary number of rules. Each rule can have an arbitrary number of
-conditions and actions. A rule fires all associated actions, once all
-of its conditions are met.
-
-A simple `etc/its/actions.config` may look like
-----
-[rule "rule1"]
- event-type = change-merged
- action = add-standard-comment
-[rule "rule2"]
- event-type = comment-added
- approval-Code-Review = -2,-1
- action = add-comment Oh my Goodness! Someone gave a negative code review in Gerrit on an associated change.
-----
-
-This snippet defines two rules ('rule1', and 'rule2'). On merging a
-change that's associated to some issues, 'rule1' adds a predefined
-standard comment for “Change Merged” to each such issue. If someone
-adds a comment to a change that is associated to some issues and votes
-“-2”, or “-1” for “Code-Review”, 'rule2' adds the comment “Oh my
-Goodness! Someone gave a negative code review in Gerrit on an
-associated change.” to each such issue.
-
-The order of rules in `etc/its/action.config` need not be
-respected. So in the above example, do not rely on 'rule1' being
-evaluated before 'rule2'.
-
-Rules
-~~~~~
-
-Each rule consists of three items: A name, a set of conditions, and a
-set of actions.
-
-The names of the rules ('rule1', and 'rule2' in the above example) are
-currently not used and only provided for convenience.
-
-For each rule the 'action' parameter is interpreted as action.
-Any other parameter of a rule is considered to be a condition.
-
-Each action of a rule is taken for events that meet all of a rule's
-conditions. If a rule contains more than one action, the order in which
-they are given need not be respected.
-
-There is no upper limit on the number of elements in a rules set of
-conditions, and set of actions. Each of those sets may be empty.
-
-Conditions
-~~~~~~~~~~
-
-The conditions are parameters of the form
-----
-name = value1, value2, ..., valueN
-----
-and (if 'value1' is not +!+) match if the event comes with a property
-'name' having 'value1', or 'value2', or ..., or 'valueN'. So for
-example to match events that come with an 'association' property
-having 'subject', or 'footer-Bug', the following condition can be
-used:
-----
-association = subject,footer-Bug
-----
-
-If 'value1' is +!+, the conditon matches if the event does not come
-with a property 'name' having 'value2', or ..., or 'valueN'. So for
-example to match events that do not come with a 'status' property
-having 'DRAFT', the following condition can be used:
-----
-status = !,DRAFT
-----
-
-[[event-properties]]
-Event Properties
-~~~~~~~~~~~~~~~~
-
-The properties exposed by events depend on the kind of the event.
-
-For all events, the event's class name is provided in the 'event'
-property. Most native Gerrit events provide the 'event-type'
-property. So 'event-type' (or 'event' for other events fired by
-plugins) allows you to write filters that fire only for a certain type
-of event.
-
-The common properties for each event are
-
-'event'::
- The event's class name.
-'issue'::
- Issue to which this event is associated. Each event is associated to
- exactly one issue. If for example an event is fired for a commit
- message that contains more than one issue id (say issue “23”,
- and issue “47"), then the event is duplicated and sent once for each
- associated issue (i.e.: once with 'issue' being +23+, and once with
- 'issue' being +47+).
-'association'::
- How the issue of property 'issue' got associated to this event. An
- event typically has several 'association' properties. Possible
- values are:
- 'somewhere'::: issue id occurs somewhere in the commit message of the
- change/the most recent patch set.
- 'subject'::: issue id occurs in the first line of the commit message
- of the change/the most recent patch set.
- 'body'::: issue id occurs after the subject but before the footer
- of the commit message of the change/the most recent patch set.
- 'footer'::: issue id occurs in the last paragraph after the subject
- of the commit message of the change/the most recent patch set.
- 'footer-<Key>'::: issue id occurs in the footer of the commit
- message of the change/the most recent patch set, and is in a line
- with a key (part before the colon).
- +
- So for example, if the footer would contain a line
-+
-----
-Fixes-Issue: issue 4711
-----
-+
-then a property 'association' with value +footer-Fixes-Issue+ would
-get added to the event for issue “4711”.
-
- 'added@<Association-Value>':::
- (only for events that allow to determine the patch set number. So
- for example, this 'association' property is not set for
- RevUpdatedEvents)
- +
- issue id occurs at '<Association-Value>' in the most recent patch
- set of the change, and either the event is for patch set 1 or the
- issue id does not occur at '<Association-Value>' in the previous
- patch set.
- +
- So for example if issue “4711” occurs in the subject of patch set
- 3 (the most recent patch set) of a change, but not in patch set 2.
- When adding a comment to this change, the event for issue “4711”
- would get a property 'association' with value +added@subject+.
-
-The further properties are listed in the event's
-corresponding subsection below:
-
-* <<event-properties-ChangeAbandonedEvent,ChangeAbandonedEvent>>
-* <<event-properties-ChangeMergedEvent,ChangeMergedEvent>>
-* <<event-properties-ChangeRestoredEvent,ChangeRestoredEvent>>
-* <<event-properties-CommentAddedEvent,CommentAddedEvent>>
-* <<event-properties-DraftPublishedEvent,DraftPublishedEvent>>
-* <<event-properties-PatchSetCreatedEvent,PatchSetCreatedEvent>>
-* <<event-properties-RefUpdatedEvent,RefUpdatedEvent>>
-* <<event-properties-change,Common properties for events on a change>>
-* <<event-properties-patch-set,Common properties for events on a patch set>>
-
-[[event-properties-ChangeAbandonedEvent]]
-ChangeAbandonedEvent
-^^^^^^^^^^^^^^^^^^^^
-
-'abandoner-email'::
- email address of the user abandoning the change.
-'abandoner-name'::
- name of the user abandoning the change.
-'abandoner-username'::
- username of the user abandoning the change.
-'event'::
- +com.google.gerrit.server.events.ChangeAbandonedEvent+
-'event-type'::
- +change-abandoned+
-'reason'::
- reason why the change has been abandoned.
-
-In addition to the above properties, the event also provides
-properties for the abandoned <<event-properties-change,change>>, and
-its most recent <<event-properties-patch-set,patch set>>.
-
-[[event-properties-ChangeMergedEvent]]
-ChangeMergedEvent
-^^^^^^^^^^^^^^^^^
-
-'event'::
- +com.google.gerrit.server.events.ChangeMergedEvent+
-'event-type'::
- +change-merged+
-'submitter-email'::
- email address of the user causing the merge of the change.
-'submitter-name'::
- name of the user causing the merge of the change.
-'submitter-username'::
- username of the user causing the merge of the change.
-
-In addition to the above properties, the event also provides
-properties for the merged <<event-properties-change,change>>, and
-its most recent <<event-properties-patch-set,patch set>>.
-
-[[event-properties-ChangeRestoredEvent]]
-ChangeRestoredEvent
-^^^^^^^^^^^^^^^^^^^
-
-'event'::
- +com.google.gerrit.server.events.ChangeRestoredEvent+
-'event-type'::
- +change-restored+
-'reason'::
- reason why the change has been restored.
-'restorer-email'::
- email address of the user restoring the change.
-'restorer-name'::
- name of the user restoring the change.
-'restorer-username'::
- username of the user restoring the change.
-
-In addition to the above properties, the event also provides
-properties for the restored <<event-properties-change,change>>, and
-its most recent <<event-properties-patch-set,patch set>>.
-
-[[event-properties-CommentAddedEvent]]
-CommentAddedEvent
-^^^^^^^^^^^^^^^^^
-
-NOTE: For consistency with the other events, the 'author-...'
-properties of the CommentAddedEvent do not refer to the author of the
-comment, but refer to the author of the change's latest patch set. The
-author of the comment is accessible via the 'commenter-...'
-properties.
-
-'commenter-email'::
- email address of the comment's author.
-'commenter-name'::
- name of the comment's author.
-'commenter-username'::
- username of the comment's author.
-'comment'::
- added comment itself.
-'event'::
- +com.google.gerrit.server.events.CommentAddedEvent+
-'event-type'::
- +comment-added+
-
-For each new or changed approval that has been made for this change, a
-property of key 'approval-<LabelName>' and the approval's value as
-value is added. So for example voting “-2” for the approval
-“Code-Review” would add the following property:
-
-'approval-Code-Review'::
- +-2+
-
-In addition to the above properties, the event also provides
-properties for the <<event-properties-change,change>> the comment was
-added for, and its most recent <<event-properties-patch-set,patch
-set>>.
-
-[[event-properties-DraftPublishedEvent]]
-DraftPublishedEvent
-^^^^^^^^^^^^^^^^^^^
-
-'event'::
- +com.google.gerrit.server.events.DraftPublishedEvent+
-'event-type'::
- +draft-published+
-
-In addition to the above properties, the event also provides
-properties for the uploaded <<event-properties-patch-set,patch set>>,
-and the <<event-properties-change,change>> it belongs to.
-
-[[event-properties-PatchSetCreatedEvent]]
-PatchSetCreatedEvent
-^^^^^^^^^^^^^^^^^^^^
-
-'event'::
- +com.google.gerrit.server.events.PatchSetCreatedEvent+
-'event-type'::
- +patchset-created+
-
-In addition to the above properties, the event also provides
-properties for the uploaded <<event-properties-patch-set,patch set>>,
-and the <<event-properties-change,change>> it belongs to.
-
-[[event-properties-RefUpdatedEvent]]
-RefUpdatedEvent
-^^^^^^^^^^^^^^^
-
-'event'::
- +com.google.gerrit.server.events.RefUpdatedEvent+
-'event-type'::
- +ref-updated+
-'project'::
- full name of the project from which a ref was updated.
-'ref'::
- git ref that has been updated (Typcially the branch, as for example
- +master+).
-'revision'::
- git commit hash the rev is pointing to now.
-'revision-old'::
- git commit hash the rev was pointing to before.
-'submitter-email'::
- email address of the user that updated the ref.
-'submitter-name'::
- name of the user that updated the ref.
-'submitter-username'::
- username of the user that updated the ref.
-
-[[event-properties-change]]
-Common properties for events on a change
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-'branch'::
- name of the branch the change belongs to.
-'change-id'::
- Change-Id for the change („I-followed by 40 hex digits” string).
-'change-number'::
- number for the change (plain integer).
-'change-url'::
- url of the change.
-'owner-email'::
- email address of the change's owner.
-'owner-name'::
- name of the change's owner.
-'owner-username'::
- username of the change's owner.
-'project'::
- full name of the project the change belongs to.
-'subject'::
- first line of the change's most recent patch set's commit message.
-'status'::
- status of the change ('null', 'NEW', 'SUBMITTED', 'DRAFT', 'MERGED',
- or 'ABANDONED' )
- +
- This property will typically be 'null' unless the used Gerrit
- incorporates
- https://gerrit-review.googlesource.com/#/c/47042/[upstream change
- 47042].
-'topic'::
- name of the topic the change belongs to.
-
-[[event-properties-patch-set]]
-Common properties for events on a patch set
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-'author-email'::
- email address of this patch set's author.
-'author-name'::
- name of this patch set's author.
-'author-username'::
- username of this patch set's author.
-'created-on'::
- Timestamp of creation of the patch set (Seconds since 1st January 1970).
-'deletions'::
- number of lines deleted by the patch set.
-'insertions'::
- number of lines inserted by the patch set.
-'is-draft'::
- 'true', if the patch set is a draft patch set, 'false' otherwise.
-'parents'::
- A list of git commit hashes that are parents to the patch set.
-'patch-set-number'::
- patch set's number within the change.
-'ref'::
- git ref for the patch set (For the 5-th patch set of change 4711, this
- will be +refs/changes/11/4711/5+).
-'revision'::
- git commit hash of the patch set
-'uploader-email'::
- email address of the user that uploaded this patch set.
-'uploader-name'::
- name of the user that uploaded this patch set.
-'uploader-username'::
- username of the user that uploaded this patch set.
-
-Actions
-~~~~~~~
-
-Parameters of the form
-----
-action = name param1 param2 ... paramN
-----
-represent the action 'name' being called with parameters 'param1',
-'param2', ... 'paramN'.
-
-'hooks-its' provides the actions:
-
-<<action-add-comment,add-comment>>::
- adds the parameters as issue comment
-<<action-add-standard-comment,add-standard-comment>>::
- adds a predefined standard comment for certain events
-<<action-add-velocity-comment,add-velocity-comment>>::
- adds a rendered Velocity template as issue comment.
-<<action-log-event,log-event>>::
- appends the event's properties to Gerrit's log.
-
-Further actions may be provided by 'hooks-its' based plugins.
-
-[[action-add-comment]]
-Action: add-comment
-^^^^^^^^^^^^^^^^^^^
-
-The 'add-comment' action adds the given parameters as comment to any associated rule.
-
-So for example
-----
-action = add-comment This is a sample command
-----
-would add a comment “This is a sample command” to associated issues.
-
-If no parameters are given, no comment gets added.
-
-[[action-add-standard-comment]]
-Action: add-standard-comment
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The 'add-standard-comment' action adds predefined comments to
-associated issues for change abandoned, merged, restored, and patch
-set created events. For other events, no comment is added to the
-associated issues.
-
-The added comments contain the person responsible for the event
-(abandoner, merger, ...), the change's subject, a reason (if one has
-been given), and a link to the change.
-
-[[action-add-velocity-comment]]
-Action: add-velocity-comment
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The 'add-velocity-comment' action renders a Velocity template for the
-event and adds the output as comment to any associated issue.
-
-So for example
-----
-action = add-velocity-comment TemplateName
-----
-would render the template `etc/its/templates/TemplateName.vm` add the
-output as comment to associated issues.
-
-If 'TemplateName' is “inline”, the Velocity template to render is not
-loaded from a file, but the template is built by joining the remaining
-parameters. So for example
-----
-action = add-velocity-comment inline Sample template using $subject property.
-----
-would render “Sample template using $subject property.” as Velocity
-template.
-
-If 'TemplateName' is not “inline”, further parameters get ignored.
-
-Any <<event-properties,property>> of the event may be used from
-templates. So for example +$subject+ in the above example refers to
-the event's subject property, and +$change-number+ would refer to the
-change's number.
-
-Additionally, the context's 'its' property provides an object that
-allows to format links using the its' syntax:
-
-'formatLink( url )'::
- Formats a link to a url.
- +
- So for example upon adding a comment to a change, the following rule
- formats a link to the change:
-+
-----
-[rule "formatLinkSampleRule"]
- event-type = comment-added
- action = add-velocity-comment inline Comment for change $change-number added. See ${its.formatLink($change-url)}
-----
-
-'formatLink( url, caption )'::
- Formats a link to a url using 'caption' to represent the url.
- +
- So for example upon adding a comment to a change, the following rule
- formats a link to the change using the change number as link
- capition:
-+
-----
-[rule "formatLinkSampleRule"]
- event-type = comment-added
- action = add-velocity-comment inline Comment for change ${its.formatLink($change-url, $change-number)} added.
------
-
-[[action-log-event]]
-Action: log-event
-^^^^^^^^^^^^^^^^^
-
-The 'log-event' action appends the event's properties to Gerrit's log.
-
-Logging happens at the info level per default, but can be overriden by
-adding the desired log level as parameter. Supported values are
-'error', 'warn', 'info', and 'debug'). So for example
-----
-action = log-event error
-----
-appends the event's properties to Gerrit's log at error level. All
-other parameters are ignored.
-
-This action is useful when testing rules or trying to refine
-conditions on rules, as it make the available properties visible.
-
-
-[[config-legacy]]
-Legacy configuration
---------------------
-
-In this section we present the legacy configuration that uses
-`etc/gerrit.config` directly. Please upgrade to the xref:config[new,
-more flexible approach].
-
-the
-plugin's section (e.g.: `bugzilla` for 'hooks-bugzilla') within
-`etc/gerrit.config`. In the following description, we use `itsName` as
-placeholder for the plugin's name. Be sure to replace it with the plugin's real
-name in the documentation of a 'hooks-its' based plugin (e.g.: Use `bugzilla`
-instead of `itsName` for 'hooks-bugzilla').
-
-[[itsName.commentOnChangeAbandoned]]itsName.commentOnChangeAbandoned::
-+
-If true, abandoning a change adds an ITS comment to the change's associated
-issue.
-+
-Default is `true`.
-
-[[itsName.commentOnChangeCreated]]itsName.commentOnChangeCreated::
-+
-If true, creating a change adds an ITS comment to the change's associated issue.
-+
-Default is `false`.
-
-[[itsName.commentOnChangeMerged]]itsName.commentOnChangeMerged::
-+
-If true, merging a change's patch set adds an ITS comment to the change's
-associated issue.
-+
-Default is `true`.
-
-[[itsName.commentOnChangeRestored]]itsName.commentOnChangeRestored::
-+
-If true, restoring an abandoned change adds an ITS comment to the change's
-associated issue.
-+
-Default is `true`.
-
-[[itsName.commentOnCommentAdded]]itsName.commentOnCommentAdded::
-+
-If true, adding a comment and/or review to a change in gerrit adds an ITS
-comment to the change's associated issue.
-+
-Default is `true`.
-
-[[itsName.commentOnFirstLinkedPatchSetCreated]]itsName.commentOnFirstLinkedPatchSetCreated::
-+
-If true, creating a patch set for a change adds an ITS comment to the change's
-associated issue, if the issue has not been mentioned in previous patch sets of
-the same change.
-+
-Default is `false`.
-
-[[itsName.commentOnPatchSetCreated]]itsName.commentOnPatchSetCreated::
-+
-If true, creating a patch set for a change adds an ITS comment to the change's
-associated issue.
-+
-Default is `true`.
-
-[[itsName.commentOnRefUpdatedGitWeb]]itsName.commentOnRefUpdatedGitWeb::
-+
-If true, updating a ref adds a GitWeb link to the associated issue.
-+
-Default is `true`.
diff --git a/pom.xml b/pom.xml
index f25d75d..deab462 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0"?>
<!--
-Copyright (C) 2008 The Android Open Source Project
+Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,16 +14,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
<modelVersion>4.0.0</modelVersion>
-
<groupId>com.googlesource.gerrit.plugins.its</groupId>
- <artifactId>its-base-parent</artifactId>
- <packaging>pom</packaging>
- <version>2.9</version>
-
+ <artifactId>its-base</artifactId>
+ <packaging>jar</packaging>
+ <version>2.10</version>
<name>Gerrit Code Review - Issue tracker support</name>
<properties>
@@ -31,227 +30,21 @@
<powermockVersion>1.5</powermockVersion>
<slf4jVersion>1.6.2</slf4jVersion>
<velocityVersion>1.6.4</velocityVersion>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
- <modules>
- <module>its-base</module>
- </modules>
-
- <licenses>
- <license>
- <name>Apache License, 2.0</name>
- <comments>
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- </comments>
- </license>
- </licenses>
-
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>2.3.2</version>
+ <version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
@@ -266,10 +59,48 @@
</plugins>
</build>
+ <dependencies>
+ <dependency>
+ <groupId>com.google.gerrit</groupId>
+ <artifactId>gerrit-plugin-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>${velocityVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4jVersion}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>${easymockVersion}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermockVersion}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${powermockVersion}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
<repositories>
<repository>
- <id>gerrit-maven</id>
- <url>https://gerrit-maven.commondatastorage.googleapis.com</url>
+ <id>gerrit-api-repository</id>
+ <url>https://gerrit-api.commondatastorage.googleapis.com/release/</url>
</repository>
- </repositories>
+ </repositories>
+
</project>
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/InitIts.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/InitIts.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/InitIts.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/its/InitIts.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/InvalidTransitionException.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/InvalidTransitionException.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/InvalidTransitionException.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/its/InvalidTransitionException.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsFacade.java
similarity index 97%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsFacade.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsFacade.java
index 2ee72a3..b4f9cd6 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsFacade.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsFacade.java
@@ -27,8 +27,6 @@
ACCESS
}
- public String name();
-
public String healthCheck(Check check)
throws IOException;
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsHookEnabledConfigEntry.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsHookEnabledConfigEntry.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsHookEnabledConfigEntry.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsHookEnabledConfigEntry.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/NoopItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/NoopItsFacade.java
similarity index 96%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/NoopItsFacade.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/its/NoopItsFacade.java
index 49d2e03..b7bfe44 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/NoopItsFacade.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/NoopItsFacade.java
@@ -75,9 +75,4 @@
}
return "";
}
-
- @Override
- public String name() {
- return "not configured";
- }
}
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/CommitMessageFetcher.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/util/CommitMessageFetcher.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/CommitMessageFetcher.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/util/CommitMessageFetcher.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
similarity index 98%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
index b2ebbc4..cdf4a09 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
@@ -43,7 +43,7 @@
* Gets issue ids from a string.
*
* @param haystack String to extract issue ids from
- * @return array of {@link Strings}. Each String being a found issue id.
+ * @return array of {@link String}. Each String being a found issue id.
*/
public String[] getIssueIds(String haystack) {
Pattern pattern = getPattern();
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractor.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractor.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractor.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractor.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractor.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractor.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsAssociationPolicy.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsAssociationPolicy.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsAssociationPolicy.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsAssociationPolicy.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java
similarity index 98%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java
index f47889e..bd8ed2c 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java
@@ -101,7 +101,7 @@
sb.append(commit.getId().getName());
sb.append(",\n");
sb.append("but do not exist in ");
- sb.append(client.name());
+ sb.append(pluginName);
sb.append(" Issue-Tracker");
details = sb.toString();
@@ -121,7 +121,7 @@
sb.append(issueExtractor.getPattern().pattern());
sb.append("\n");
sb.append(" and are pointing to existing tickets on ");
- sb.append(client.name());
+ sb.append(pluginName);
sb.append(" Issue-Tracker");
details = sb.toString();
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Condition.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Condition.java
similarity index 97%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Condition.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Condition.java
index 5fc79a8..aca340e 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Condition.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Condition.java
@@ -24,6 +24,8 @@
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.hooks.workflow.action.Action;
+
/**
* A condition as used in {@link Rule}, as precondition to {@link Action}s.
* <p>
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilter.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilter.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilter.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilter.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddComment.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddComment.java
similarity index 93%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddComment.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddComment.java
index ac19c2e..123f119 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddComment.java
@@ -19,6 +19,7 @@
import org.eclipse.jgit.lib.Config;
import com.google.common.base.Strings;
+import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.data.AccountAttribute;
@@ -30,6 +31,7 @@
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
import com.google.inject.Inject;
+
import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
import com.googlesource.gerrit.plugins.hooks.util.IssueExtractor;
@@ -48,9 +50,12 @@
@Inject
private IssueExtractor issueExtractor;
+ @Inject @PluginName
+ private String pluginName;
+
@Override
public void doFilter(CommentAddedEvent hook) throws IOException {
- if (!(gerritConfig.getBoolean(its.name(), null, "commentOnCommentAdded",
+ if (!(gerritConfig.getBoolean(pluginName, null, "commentOnCommentAdded",
true))) {
return;
}
@@ -61,7 +66,7 @@
@Override
public void doFilter(ChangeMergedEvent hook) throws IOException {
- if (!(gerritConfig.getBoolean(its.name(), null, "commentOnChangeMerged",
+ if (!(gerritConfig.getBoolean(pluginName, null, "commentOnChangeMerged",
true))) {
return;
}
@@ -72,7 +77,7 @@
@Override
public void doFilter(ChangeAbandonedEvent hook) throws IOException {
- if (!(gerritConfig.getBoolean(its.name(), null, "commentOnChangeAbandoned",
+ if (!(gerritConfig.getBoolean(pluginName, null, "commentOnChangeAbandoned",
true))) {
return;
}
@@ -82,7 +87,7 @@
@Override
public void doFilter(ChangeRestoredEvent hook) throws IOException {
- if (!(gerritConfig.getBoolean(its.name(), null, "commentOnChangeRestored",
+ if (!(gerritConfig.getBoolean(pluginName, null, "commentOnChangeRestored",
true))) {
return;
}
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToChangeId.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToChangeId.java
similarity index 94%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToChangeId.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToChangeId.java
index 3a8314b..8d6b4ca 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToChangeId.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToChangeId.java
@@ -24,6 +24,7 @@
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
+import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -32,6 +33,7 @@
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
+
import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
import com.googlesource.gerrit.plugins.hooks.util.IssueExtractor;
@@ -54,6 +56,10 @@
@Inject
private ReviewDb db;
+ @Inject @PluginName
+ private String pluginName;
+
+
/**
* Filter issues to those that occur for the first time in a change
*
@@ -97,14 +103,14 @@
@Override
public void doFilter(PatchSetCreatedEvent patchsetCreated)
throws IOException, OrmException {
- boolean addPatchSetComment = gerritConfig.getBoolean(its.name(), null,
+ boolean addPatchSetComment = gerritConfig.getBoolean(pluginName, null,
"commentOnPatchSetCreated", true);
boolean addChangeComment = "1".equals(patchsetCreated.patchSet.number) &&
- gerritConfig.getBoolean(its.name(), null, "commentOnChangeCreated",
+ gerritConfig.getBoolean(pluginName, null, "commentOnChangeCreated",
false);
- boolean addFirstLinkedPatchSetComment = gerritConfig.getBoolean(its.name(),
+ boolean addFirstLinkedPatchSetComment = gerritConfig.getBoolean(pluginName,
null, "commentOnFirstLinkedPatchSetCreated", false);
if (addPatchSetComment || addFirstLinkedPatchSetComment || addChangeComment) {
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToGitWeb.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToGitWeb.java
similarity index 95%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToGitWeb.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToGitWeb.java
index da582f8..cee6d79 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToGitWeb.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterAddRelatedLinkToGitWeb.java
@@ -28,10 +28,12 @@
import com.google.gerrit.common.data.GitWebType;
import com.google.gerrit.common.data.ParameterizedString;
+import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.httpd.GitWebConfig;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.inject.Inject;
+
import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
import com.googlesource.gerrit.plugins.hooks.util.IssueExtractor;
@@ -53,9 +55,12 @@
@Inject
private IssueExtractor issueExtractor;
+ @Inject @PluginName
+ private String pluginName;
+
@Override
public void doFilter(RefUpdatedEvent hook) throws IOException {
- if (!(gerritConfig.getBoolean(its.name(), null, "commentOnRefUpdatedGitWeb",
+ if (!(gerritConfig.getBoolean(pluginName, null, "commentOnRefUpdatedGitWeb",
true))) {
return;
}
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterChangeState.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterChangeState.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterChangeState.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/GerritHookFilterChangeState.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Property.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Property.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Property.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Property.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Rule.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Rule.java
similarity index 97%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Rule.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Rule.java
index 512af73..5fb58d1 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Rule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/Rule.java
@@ -59,7 +59,7 @@
/**
* Adds an action to the rule.
*
- * @param action The action to add.
+ * @param actionRequest The action to add.
*/
public void addActionRequest(ActionRequest actionRequest) {
actionRequests.add(actionRequest);
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBase.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBase.java
similarity index 67%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBase.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBase.java
index 101dfa6..685a639 100644
--- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBase.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBase.java
@@ -15,16 +15,16 @@
package com.googlesource.gerrit.plugins.hooks.workflow;
import java.io.File;
+import java.io.IOException;
import java.util.Collection;
-import java.util.Collections;
import com.google.common.collect.Lists;
import com.google.gerrit.server.config.SitePath;
import com.google.inject.Inject;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,7 +38,7 @@
* File (relative to site) to load rules from
*/
private static final String ITS_CONFIG_FILE = "etc" + File.separatorChar +
- "its" + File.separator + "action.config";
+ "its" + File.separator + "actions.config";
/**
* The section for rules within {@link #ITS_CONFIG_FILE}
@@ -69,22 +69,26 @@
this.ruleFactory = ruleFactory;
this.conditionFactory = conditionFactory;
this.actionRequestFactory = actionRequestFactory;
- loadRules();
+ reloadRules();
}
/**
- * Loads the rules for the RuleBase.
+ * Adds rules from a file to the the RuleBase.
+ * <p>
+ * If the given file does not exist, it is silently ignored
*
- * Consider using {@link #loadRules()@}, as that method only loads the rules,
- * if they have not yet been loaded.
+ * @param ruleFile File from which to read the rules
*/
- private void forceLoadRules() throws Exception {
- File configFile = new File(sitePath, ITS_CONFIG_FILE);
- if (configFile.exists()) {
- FileBasedConfig cfg = new FileBasedConfig(configFile, FS.DETECTED);
- cfg.load();
+ private void addRulesFromFile(File ruleFile) {
+ if (ruleFile.exists()) {
+ FileBasedConfig cfg = new FileBasedConfig(ruleFile, FS.DETECTED);
+ try {
+ cfg.load();
+ } catch (IOException | ConfigInvalidException e) {
+ log.error("Invalid ITS action configuration", e);
+ return;
+ }
- rules = Lists.newArrayList();
Collection<String> subsections = cfg.getSubsections(RULE_SECTION);
for (String subsection : subsections) {
Rule rule = ruleFactory.create(subsection);
@@ -106,24 +110,36 @@
rules.add(rule);
}
} else {
- // configFile does not exist.
- log.warn("ITS actions configuration file (" + configFile + ") does not exist.");
- rules = Collections.emptySet();
+ log.warn("ITS actions configuration file (" + ruleFile + ") does not exist.");
}
}
/**
- * Loads the rules for the RuleBase, if they have not yet been loaded.
+ * Loads the rules for the RuleBase.
*/
- private void loadRules() {
- if (rules == null) {
- try {
- forceLoadRules();
- } catch (Exception e) {
- log.error("Invalid ITS action configuration", e);
- rules = Collections.emptySet();
- }
+ private void reloadRules() {
+ rules = Lists.newArrayList();
+
+ // Add rules from file with typo in filename
+ //
+ // While the documentation called for "actions.config" (Trailing "s" in
+ // "actions"), the code previously only loaded "action.config" (No
+ // trailing "s" in "action"). To give users time to gracefully migrate to
+ // "actions.config" (with trailing "s", we (for now) load files from both
+ // locations, but consider "actions.config" (with trailing "s" the
+ // canonical place.
+ File faultyNameRuleFile = new File(sitePath, "etc" + File.separatorChar
+ + "its" + File.separator + "action.config");
+ if (faultyNameRuleFile.exists()) {
+ log.warn("Loading rules from deprecated 'etc/its/action.config' (No "
+ + "trailing 's' in 'action'). Please migrate to "
+ + "'etc/its/actions.config' (Trailing 's' in 'actions').");
+ addRulesFromFile(faultyNameRuleFile);
}
+
+ // Add global rules
+ File globalRuleFile = new File(sitePath, ITS_CONFIG_FILE);
+ addRulesFromFile(globalRuleFile);
}
/**
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddComment.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddComment.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddComment.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddComment.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityComment.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityComment.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityComment.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityComment.java
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEvent.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEvent.java
similarity index 100%
rename from its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEvent.java
rename to src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEvent.java
diff --git a/its-base/src/main/resources/Documentation/.gitignore b/src/main/resources/Documentation/.gitignore
similarity index 100%
rename from its-base/src/main/resources/Documentation/.gitignore
rename to src/main/resources/Documentation/.gitignore
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
new file mode 100644
index 0000000..343ec34
--- /dev/null
+++ b/src/main/resources/Documentation/about.md
@@ -0,0 +1,26 @@
+its-base
+========
+
+`its-base` is a common stub for Gerrit plugins that connect to issue
+tracking systems ("ITS"). `its-base` on its own is not meant to be
+installed as plugin to a Gerrit site. Instead `its-base` provides
+common functionality to other plugins, like:
+
+* [its-bugzilla][its-bugzilla]
+* [its-jira][its-jira]
+* [its-rtc][its-rtc]
+
+[its-bugzilla]: https://gerrit-review.googlesource.com/#/admin/projects/plugins/its-bugzilla
+[its-jira]: https://gerrit-review.googlesource.com/#/admin/projects/plugins/its-jira
+[its-rtc]: https://gerrit-review.googlesource.com/#/admin/projects/plugins/its-rtc
+
+`its-base` provides means to:
+
+* Add comments to an ITS (based on a user-defined rules, like "Add a
+ comment to the ITS, if a change references the respective issue").
+* Change status of ITS entries (based on a user-defined rules, like
+ "Set status to `resolved` if a change gets merged that references
+ the respective issue").
+* (De-)activate on per-project base.
+
+<span></span>
diff --git a/src/main/resources/Documentation/build.md b/src/main/resources/Documentation/build.md
new file mode 100644
index 0000000..c6afec9
--- /dev/null
+++ b/src/main/resources/Documentation/build.md
@@ -0,0 +1,60 @@
+Build
+=====
+
+This base library for ITS-based plugins is built with Buck.
+
+Clone or link this plugin to the plugins directory of Gerrit's source
+tree, and issue the command:
+
+```
+ buck build plugins/its-base
+```
+
+The output is created in
+
+```
+ buck-out/gen/plugins/its-base/its-base.jar
+ buck-out/gen/plugins/its-base/lib__its-base__plugin__output/its-base__plugin.jar
+```
+
+This project can be imported into the Eclipse IDE:
+
+```
+ ./tools/eclipse/project.py
+```
+
+To execute the tests run:
+
+```
+ buck test --all --include its-base
+```
+
+Note that for compatibility reasons a Maven build is provided, but is
+considered to be deprecated and will be removed in a future version of
+this plugin.
+
+To build with Maven, change directory to the plugin folder and issue the
+command:
+
+```
+ mvn clean package
+```
+
+When building with Maven, the Gerrit Plugin API must be available.
+
+Note that the ITS-based plugins require `its-base__plugin` library:
+
+```
+[...]
+ deps = [
+ '//plugins/its-base:its-base__plugin',
+ ],
+[...]
+```
+
+How to build the Gerrit Plugin API is described in the [Gerrit
+documentation](../../../Documentation/dev-buck.html#_extension_and_plugin_api_jar_files).
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
\ No newline at end of file
diff --git a/src/main/resources/Documentation/config-common.md b/src/main/resources/Documentation/config-common.md
new file mode 100644
index 0000000..4ad3c97
--- /dev/null
+++ b/src/main/resources/Documentation/config-common.md
@@ -0,0 +1,208 @@
+Common configuration for `its-base`-based plugins
+=================================================
+
+#### Table of Contents
+* [Identifying ITS ids][identifying-its-ids]
+* [Enabling ITS integration][enabling-its-integration]
+* [Configuring rules of when to take which actions in the ITS][configure-rules]
+* [Legacy configuration][legacy-configuration]
+
+
+
+[identifying-its-ids]: #identifying-its-ids
+<a name="identifying-its-ids">Identifying ITS ids</a>
+-----------------------------------------------------
+
+In order to extract ITS ids from commit messages, @PLUGIN@ uses
+[commentlink][upstream-comment-link-doc]s of name "`@PLUGIN@`".
+
+The first group of `commentlink.@PLUGIN@.match` is considered the
+issue id.
+
+So for example having
+
+```
+[commentLink "@PLUGIN@"]
+ match = [Bb][Uu][Gg][ ]*([1-9][0-9]*)
+ html = "<a href=\"http://my.issure.tracker.example.org/show_bug.cgi?id=$1\">(bug $1)</a>"
+ association = SUGGESTED
+```
+
+in `etc/gerrit.config` would allow to match the issues `4711`, `167`
+from a commit message like
+
+```
+Sample commit message relating to bug 4711, and bug 167.
+```
+
+By setting a `commentlink`'s `association` (see above's example), it
+is possible to require commits to carry ITS references; the following
+values are supported (default is `OPTIONAL`):
+
+MANDATORY
+: One or more issue-ids are required in the git commit message, otherwise
+ the git push will be rejected.
+
+SUGGESTED
+: Whenever the git commit message does not contain one or more issue-ids,
+ a warning message is displayed as a suggestion on the client.
+
+OPTIONAL
+: Bug-ids are liked when found in the git commit message, no warning is
+ displayed otherwise.
+
+
+
+[enabling-its-integration]: #enabling-its-integration
+<a name="enabling-its-integration">Enabling ITS integration</a>
+---------------------------------------------------------------
+
+It can be configured per project whether the issue tracker
+integration is enabled or not. To enable the issue tracker integration
+for a project the project must have the following entry in its
+`project.config` file in the `refs/meta/config` branch:
+
+```
+ [plugin "@PLUGIN@"]
+ enabled = true
+```
+
+If `plugin.@PLUGIN@.enabled` is not specified in the `project.config`
+file the value is inherited from the parent project. If it is not
+set on any parent project the issue integration is disabled for this
+project.
+
+By setting `plugin.@PLUGIN@.enabled` to true in the `project.config`
+of the `All-Projects` project the issue tracker integration can be
+enabled by default for all projects. During the initialization of the
+plugin you are asked if the issue integration should be enabled by
+default for all projects and if yes this setting in the
+`project.config` of the `All-Projects` project is done automatically.
+
+With this it is possible to support integration with multiple
+issue tracker systems on a server. E.g. a project can choose if it
+wants to enable integration with Jira or with Bugzilla.
+
+If child projects must not be allowed to disable the issue tracker
+system integration a project can enforce the issue tracker system
+integration for all child projects by setting
+`plugin.@PLUGIN@.enabled` to `enforced`.
+
+The issue tracker system integration can be limited to specific
+branches by setting `plugin.@PLUGIN@.branch`. The branches may be
+configured using explicit branch names, ref patterns, or regular
+expressions. Multiple branches may be specified.
+
+E.g. to limit the issue tracker system integration to the `master`
+branch and all stable branches the following could be configured:
+
+```
+ [plugin "@PLUGIN@"]
+ enabled = true
+ branch = refs/heads/master
+ branch = ^refs/heads/stable-.*
+```
+
+
+
+[configure-rules]: #configure-rules
+<a name="configure-rules">Configuring rules of when to take which actions in the ITS</a>
+----------------------------------------------------------------------------------------
+
+Setting up which event in Gerrit (E.g.: “Change Merged”, or “User
+‘John Doe’ voted ‘+2’ for ‘Code-Review’ on a change”) should trigger
+which action on the ITS (e.g.: “Set issue's status to ‘Resolved’”) is
+configured through a [rule base][rule-base] in
+`etc/its/actions.config`.
+
+[rule-base]: config-rulebase-common.html
+
+
+
+[multiple-its]: #multiple-its
+<a name="mutiple-its">Multiple ITS</a>
+--------------------------------------
+
+Although not a common setup the @PLUGIN@ plugin supports connecting
+Gerrit to multiple issue tracking systems.
+
+For example users may want to reference issues from two independent
+issue tracking systems (i.e. a Bugzilla and a Jira instance). In
+this configuration you can simply install both its plugins and
+configure them as described.
+
+In situations where users want to reference issues from multiple
+instances of the same issue tracking system (i.e. two independent
+Bugzilla instances) they can simply create two its-bugzilla plugin
+files with different names (i.e. its-bugzilla-external.jar and
+its-bugzilla-internal.jar). Gerrit will give each plugin the same
+name as the file name (minus the extension). You can view the names
+by going to the Gerrit UI under menu Plugins -> Installed. Now you
+just need to use the appropriate name to configure each plugin.
+
+
+
+
+[legacy-configuration]: #legacy-configuration
+<a name="legacy-configuration">Legacy configuration</a>
+-------------------------------------------------------
+
+In this section we present the legacy configuration that uses
+`etc/gerrit.config` directly. As this legacy part will be removed at
+some point, please upgrade to the rule [rule based
+approach][rule-base].
+
+The following configuration settings are available:
+
+`@PLUGIN@.commentOnChangeAbandoned`
+: If true, abandoning a change adds an ITS comment to the change's
+ associated issue.
+
+ Default is `true`.
+
+`@PLUGIN@.commentOnChangeCreated`
+: If true, creating a change adds an ITS comment to the change's
+ associated issue.
+
+ Default is `false`.
+
+`@PLUGIN@.commentOnChangeMerged`
+: If true, merging a change's patch set adds an ITS comment to
+ the change's associated issue.
+
+ Default is `true`.
+
+`@PLUGIN@.commentOnChangeRestored`
+: If true, restoring an abandoned change adds an ITS comment to
+ the change's associated issue.
+
+ Default is `true`.
+
+`@PLUGIN@.commentOnCommentAdded`
+: If true, adding a comment and/or review to a change in Gerrit
+ adds an ITS comment to the change's associated issue.
+
+ Default is `true`.
+
+`@PLUGIN@.commentOnFirstLinkedPatchSetCreated`
+: If true, creating a patch set for a change adds an ITS comment
+ to the change's associated issue, if the issue has not been
+ mentioned in previous patch sets of the same change.
+
+ Default is `false`.
+
+`@PLUGIN@.commentOnPatchSetCreated`
+: If true, creating a patch set for a change adds an ITS comment
+ to the change's associated issue.
+
+ Default is `true`.
+
+`@PLUGIN@.commentOnRefUpdatedGitWeb`
+: If true, updating a ref adds a GitWeb link to the associated
+ issue.
+
+ Default is `true`.
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
diff --git a/src/main/resources/Documentation/config-connectivity.md b/src/main/resources/Documentation/config-connectivity.md
new file mode 100644
index 0000000..0731c94
--- /dev/null
+++ b/src/main/resources/Documentation/config-connectivity.md
@@ -0,0 +1,16 @@
+Configuring connectivity for @PLUGIN@
+=====================================
+
+```
+THIS FILE IS A PLACEHOLDER.
+
+PLEASE GET THE @PLUGIN@ MAINTAINER TO DOCUMENT WHAT SETTINGS ARE
+NEEDED.
+
+UNTIL THEN, PLEASE CHECK @PLUGIN@'s SOURCE CODE ON HOW TO SET UP
+CONNECTIVITY.
+```
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
\ No newline at end of file
diff --git a/src/main/resources/Documentation/config-rulebase-common.md b/src/main/resources/Documentation/config-rulebase-common.md
new file mode 100644
index 0000000..4712e31
--- /dev/null
+++ b/src/main/resources/Documentation/config-rulebase-common.md
@@ -0,0 +1,594 @@
+Rule base configuration
+=======================
+
+#### Table of Contents
+* [Overview][overview]
+* [Rules][rules]
+* [Conditions][conditions]
+* [Event Properties][event-properties]
+* [Actions][actions]
+
+[overview]: #overview
+<a name="overview">Overview</a>
+-------------------------------
+
+In this part we describe how to specify which events in Gerrit (E.g.:
+“Change Merged”, or “User ‘John Doe’ voted ‘+2’ for ‘Code-Review’ on a
+change”) trigger which actions (e.g.: “Set issue's status to
+‘Resolved’”) on the ITS.
+
+Actions on the ITS and conditions for the action to take place are
+configured through the rule base in `etc/its/actions.config` in the
+site directory. The rule base is a git config file, and may contain an
+arbitrary number of rules. Each rule can have an arbitrary number of
+conditions and actions. A rule fires all associated actions, once all
+of its conditions are met.
+
+A simple `etc/its/actions.config` may look like
+
+```
+[rule "rule1"]
+ event-type = change-merged
+ action = add-standard-comment
+[rule "rule2"]
+ event-type = comment-added
+ approval-Code-Review = -2,-1
+ action = add-comment Oh my Goodness! Someone gave a negative code review in Gerrit on an associated change.
+```
+
+This snippet defines two rules (`rule1`, and `rule2`). On merging a
+change that's associated to some issues, `rule1` adds a predefined
+standard comment for “Change Merged” to each such issue. If someone
+adds a comment to a change that is associated to some issues and votes
+“-2”, or “-1” for “Code-Review”, `rule2` adds the comment “Oh my
+Goodness! Someone gave a negative code review in Gerrit on an
+associated change.” to each such issue.
+
+The order of rules in `etc/its/actions.config` need not be
+respected. So in the above example, do not rely on `rule1` being
+evaluated before `rule2`.
+
+[rules]: #rules
+<a name="rules">Rules</a>
+-------------------------
+
+Each rule consists of three items: A name, a set of conditions, and a
+set of actions.
+
+The rule's name (`rule1`, and `rule2` in the above example) is
+currently not used and only provided for convenience.
+
+For each rule the option `action` is interpreted as action. Any other
+option of a rule is considered a condition.
+
+Each of a rule's actions is taken for events that meet all of a
+rule's conditions. If a rule contains more than one action
+specifications, the order in which they are given need not be
+respected.
+
+There is no upper limit on the number of elements in a rules set of
+conditions, and set of actions. Each of those sets may be empty.
+
+[conditions]: #conditions
+<a name="conditions">Conditions</a>
+-----------------------------------
+
+The conditions are lines of the form
+
+```
+ name = value1, value2, ..., valueN
+```
+
+and match (if 'value1' is not `!`), if the event comes with a property
+'name' having 'value1', or 'value2', or ..., or 'valueN'. So for
+example to match events that come with an `association` property
+having `subject`, or `footer-Bug`, the following condition can be
+used:
+
+```
+ association = subject,footer-Bug
+```
+
+If 'value1' is `!`, the conditon matches if the event does not come
+with a property 'name' having 'value2', or ..., or 'valueN'. So for
+example to match events that do not come with a `status` property
+having `DRAFT`, the following condition can be used:
+
+```
+ status = !,DRAFT
+```
+
+[event-properties]: #event-properties
+<a name="event-properties">Event Properties</a>
+-----------------------------------------------
+
+The properties exposed by events depend on the kind of event.
+
+For all events, the event's class name is provided in the `event`
+property. Most native Gerrit events provide the `event-type`
+property. So `event-type` (or `event` for other events fired by
+plugins) allows you to write filters that fire only for a certain type
+of event.
+
+The common properties for each event are
+
+`event`
+: The event's class name.
+
+`issue`
+: Issue to which this event is associated. Each event is associated to
+ exactly one issue. If for example an event is fired for a commit
+ message, that would contain more than one issue id (say issue “23”,
+ and issue “47”), then the event is duplicated and sent once for each
+ associated issue (i.e.: once with `issue` being `23`, and once with
+ `issue` being `47`).
+
+`association`
+: How the issue of property `issue` got associated to this event.
+ See [Property: `association`][property-association].
+
+
+The further properties are listed in the event's
+corresponding subsection below:
+
+* [ChangeAbandonedEvent][event-properties-ChangeAbandonedEvent]
+* [ChangeMergedEvent][event-properties-ChangeMergedEvent]
+* [ChangeRestoredEvent][event-properties-ChangeRestoredEvent]
+* [CommentAddedEvent][event-properties-CommentAddedEvent]
+* [DraftPublishedEvent][event-properties-DraftPublishedEvent]
+* [PatchSetCreatedEvent][event-properties-PatchSetCreatedEvent]
+* [RefUpdatedEvent][event-properties-RefUpdatedEvent]
+* [Common properties for events on a change][event-properties-change]
+* [Common properties for events on a patch set][event-properties-patch-set]
+
+[property-association]: #property-association
+### <a name="property-association">Property: `association`</a>
+
+The property `association` describes how the `issue` got associated to
+this event.
+
+An event typically has several `association` properties. Possible
+values are:
+
+`somewhere`
+: issue id occurs somewhere in the commit message of the change/the
+ most recent patch set.
+
+`subject`
+: issue id occurs in the first line of the commit message of the
+ change/the most recent patch set.
+
+`body`
+: issue id occurs after the subject but before the footer of the
+ commit message of the change/the most recent patch set.
+
+`footer`
+: issue id occurs in the last paragraph after the subject of the
+ commit message of the change/the most recent patch set
+
+`footer-<Key>`
+: issue id occurs in the footer of the commit message of the
+ change/the most recent patch set, and is in a line with a key
+ (part before the colon).
+
+ So for example, if the footer would contain a line
+
+ ```
+Fixes-Issue: issue 4711
+```
+
+ then a property `association` with value `footer-Fixes-Issue`
+ would get added to the event for issue “4711”.
+
+`added@<Association-Value>`
+: (only for events that allow to determine the patch set number.
+ So for example, this `association` property is not set for
+ RevUpdatedEvents)
+
+ issue id occurs at `<Association-Value>` in the most recent
+ patch set of the change, and either the event is for patch set
+ 1 or the issue id does not occur at `<Association-Value>` in
+ the previous patch set.
+
+ So for example if issue “4711” occurs in the subject of patch
+ set 3 (the most recent patch set) of a change, but not in
+ patch set 2. When adding a comment to this change, the event
+ for issue “4711” would get a property 'association' with value
+ `added@subject`.
+
+[event-properties-ChangeAbandonedEvent]: #event-properties-ChangeAbandonedEvent
+### <a name="event-properties-ChangeAbandonedEvent">ChangeAbandonedEvent</a>
+
+`abandoner-email`
+: email address of the user abandoning the change.
+
+`abandoner-name`
+: name of the user abandoning the change.
+
+`abandoner-username`
+: username of the user abandoning the change.
+
+`event`
+: `com.google.gerrit.server.events.ChangeAbandonedEvent`
+
+`event-type`
+: `change-abandoned`
+
+`reason`
+: reason why the change has been abandoned.
+
+In addition to the above properties, the event also provides
+properties for the abandoned [Change][event-properties-change], and
+its most recent [Patch Set][event-properties-patch-set].
+
+[event-properties-ChangeMergedEvent]: #event-properties-ChangeMergedEvent
+### <a name="event-properties-ChangeMergedEvent">ChangeMergedEvent</a>
+
+`event`
+: `com.google.gerrit.server.events.ChangeMergedEvent`
+
+`event-type`
+: `change-merged`
+
+`submitter-email`
+: email address of the user causing the merge of the change.
+
+`submitter-name`
+: name of the user causing the merge of the change.
+
+`submitter-username`
+: username of the user causing the merge of the change.
+
+In addition to the above properties, the event also provides
+properties for the merged [Change][event-properties-change], and its
+most recent [Patch Set][event-properties-patch-set].
+
+[event-properties-ChangeRestoredEvent]: #event-properties-ChangeRestoredEvent
+### <a name="event-properties-ChangeRestoredEvent">ChangeRestoredEvent</a>
+
+`event`
+: `com.google.gerrit.server.events.ChangeRestoredEvent`
+
+`event-type`
+: `change-restored`
+
+`reason`
+: reason why the change has been restored.
+
+`restorer-email`
+: email address of the user restoring the change.
+
+`restorer-name`
+: name of the user restoring the change.
+
+`restorer-username`
+: username of the user restoring the change.
+
+In addition to the above properties, the event also provides
+properties for the restored [Change][event-properties-change], and it's
+most recent [Patch Set][event-properties-patch-set].
+
+[event-properties-CommentAddedEvent]: #event-properties-CommentAddedEvent
+### <a name="event-properties-CommentAddedEvent">CommentAddedEvent</a>
+
+NOTE: For consistency with the other events, the `author-...`
+properties of the CommentAddedEvent do not refer to the author of the
+comment, but refer to the author of the change's latest patch set. The
+author of the comment is accessible via the `commenter-...`
+properties.
+
+`commenter-email`
+: email address of the comment's author.
+
+`commenter-name`
+: name of the comment's author.
+
+`commenter-username`
+: username of the comment's author.
+
+`comment`
+: added comment itself.
+
+`event`
+: `com.google.gerrit.server.events.CommentAddedEvent+
+
+`event-type`
+: `comment-added`
+
+For each new or changed approval that has been made for this change, a
+property of key `approval-<LabelName>` and the approval's value as
+value is added. So for example voting “-2” for the approval
+“Code-Review” would add the following property:
+
+`approval-Code-Review`
+: `-2`
+
+In addition to the above properties, the event also provides
+properties for the [Change][event-properties-change] the comment was
+added for, and it's most recent [Patch Set][event-properties-patch-set].
+
+[event-properties-DraftPublishedEvent]: #event-properties-DraftPublishedEvent
+### <a name="event-properties-DraftPublishedEvent">DraftPublishedEvent</a>
+
+`event`
+: `com.google.gerrit.server.events.DraftPublishedEvent`
+
+`event-type`
+: `draft-published`
+
+In addition to the above properties, the event also provides
+properties for the uploaded [Patch Set][event-properties-patch-set],
+and the [Change][event-properties-change] it belongs to.
+
+[event-properties-PatchSetCreatedEvent]: #event-properties-PatchSetCreatedEvent
+### <a name="event-properties-PatchSetCreatedEvent">PatchSetCreatedEvent</a>
+
+`event`
+: `com.google.gerrit.server.events.PatchSetCreatedEvent`
+
+`event-type`
+: `patchset-created`
+
+In addition to the above properties, the event also provides
+properties for the uploaded [Patch Set][event-properties-patch-set],
+and the [Change][event-properties-change] it belongs to.
+
+[event-properties-RefUpdatedEvent]: #event-properties-RefUpdatedEvent
+### <a name="event-properties-RefUpdatedEvent">RefUpdatedEvent</a>
+
+`event`
+: `com.google.gerrit.server.events.RefUpdatedEvent`
+
+`event-type`
+: `ref-updated`
+
+`project`
+: full name of the project from which a ref was updated.
+
+`ref`
+: git ref that has been updated (Typcially the branch, as for example
+ `master`).
+
+`revision`
+: git commit hash the rev is pointing to now.
+
+`revision-old`
+: git commit hash the rev was pointing to before.
+
+`submitter-email`
+: email address of the user that updated the ref.
+
+`submitter-name`
+: name of the user that updated the ref.
+
+`submitter-username`
+: username of the user that updated the ref.
+
+[event-properties-change]: #event-properties-change
+### <a name="event-properties-change">Common properties for events on a change</a>
+
+`branch`
+: name of the branch the change belongs to.
+
+`change-id`
+: Change-Id for the change („I-followed by 40 hex digits” string).
+
+`change-number`
+: number for the change (plain integer).
+
+`change-url`
+: url of the change.
+
+`owner-email`
+: email address of the change's owner.
+
+`owner-name`
+: name of the change's owner.
+
+`owner-username`
+: username of the change's owner.
+
+`project`
+: full name of the project the change belongs to.
+
+`subject`
+: first line of the change's most recent patch set's commit message.
+
+`status`
+: status of the change (`null`, `NEW`, `SUBMITTED`, `DRAFT`, `MERGED`,
+ or `ABANDONED` )
+
+`topic`
+: name of the topic the change belongs to.
+
+[event-properties-patch-set]: #event-properties-patch-set
+### <a name="event-properties-patch-set">Common properties for events on a patch set</a>
+
+`author-email`
+: email address of this patch set's author.
+
+`author-name`
+: name of this patch set's author.
+
+`author-username`
+: username of this patch set's author.
+
+`created-on`
+: Timestamp of creation of the patch set (Seconds since 1st January 1970).
+
+`deletions`
+: number of lines deleted by the patch set.
+
+`insertions`
+: number of lines inserted by the patch set.
+
+`is-draft`
+: 'true', if the patch set is a draft patch set, 'false' otherwise.
+
+`parents`
+: A list of git commit hashes that are parents to the patch set.
+
+`patch-set-number`
+: patch set's number within the change.
+
+`ref`
+: git ref for the patch set (For the 5-th patch set of change 4711, this
+ will be `refs/changes/11/4711/5`).
+
+`revision`
+: git commit hash of the patch set
+
+`uploader-email`
+: email address of the user that uploaded this patch set.
+
+`uploader-name`
+: name of the user that uploaded this patch set.
+
+`uploader-username`
+: username of the user that uploaded this patch set.
+
+[actions]: #actions
+<a name="actions">Actions</a>
+-----------------------------
+
+Lines of the form
+
+```
+ action = name param1 param2 ... paramN
+```
+
+represent the action `name` being called with parameters `param1`,
+`param2`, ... `paramN`.
+
+The following actions are available:
+
+[`add-comment`][action-add-comment]
+: adds the parameters as issue comment
+
+[`add-standard-comment`][action-add-standard-comment]
+: adds a predefined standard comment for certain events
+
+[`add-velocity-comment`][action-add-velocity-comment]
+: adds a rendered Velocity template as issue comment
+
+[`log-event`][action-log-event]
+: appends the event's properties to Gerrit's log
+
+[Further actions][further-actions] may be provided by @PLUGIN@.
+
+[further-actions]: config-rulebase-plugin-actions.md
+
+[action-add-comment]: #action-add-comment
+### <a name="action-add-comment">Action: add-comment</a>
+
+The `add-comment` action adds the given parameters as comment to any
+associated rule.
+
+So for example
+
+```
+ action = add-comment This is a sample command
+```
+
+would add a comment “This is a sample command” to associated issues.
+
+If no parameters are given, no comment gets added.
+
+[action-add-standard-comment]: #action-add-standard-comment
+### <a name="action-add-standard-comment">Action: add-standard-comment</a>
+
+The `add-standard-comment` action adds predefined comments to
+associated issues for change abandoned, merged, restored, and patch
+set created events. For other events, no comment is added to the
+associated issues.
+
+The added comments contain the person responsible for the event
+(abandoner, merger, ...), the change's subject, a reason (if one has
+been given), and a link to the change.
+
+[action-add-comment]: #action-add-comment
+### <a name="action-add-comment">Action: add-comment</a>
+
+[action-add-velocity-comment]: #action-add-velocity-comment
+### <a name="action-add-velocity-comment">Action: add-velocity-comment</a>
+
+The `add-velocity-comment` action renders a Velocity template for the
+event and adds the output as comment to any associated issue.
+
+So for example
+
+```
+ action = add-velocity-comment TemplateName
+```
+
+would render the template `etc/its/templates/TemplateName.vm` add the
+output as comment to associated issues.
+
+If 'TemplateName' is `inline`, the Velocity template to render is not
+loaded from a file, but the template is built by joining the remaining
+parameters. So for example
+
+```
+ action = add-velocity-comment inline Sample template using $subject property.
+```
+
+would render “Sample template using $subject property.” as Velocity
+template.
+
+If 'TemplateName' is not `inline`, further parameters get ignored.
+
+Any [property][event-properties] of the event may be used from
+templates. So for example `$subject` in the above example refers to
+the event's subject property, and `$change-number` would refer to the
+change's number.
+
+Additionally, the context's `its` property provides an object that
+allows to format links using the its' syntax:
+
+`formatLink( url )`
+: Formats a link to a url.
+
+ So for example upon adding a comment to a change, the
+ following rule formats a link to the change:
+
+ ```
+[rule "formatLinkSampleRule"]
+ event-type = comment-added
+ action = add-velocity-comment inline Comment for change $change-number added. See ${its.formatLink($change-url)}
+```
+
+`formatLink( url, caption )`
+: Formats a link to a url using 'caption' to represent the url.
+
+ So for example upon adding a comment to a change, the following rule
+ formats a link to the change using the change number as link
+ capition:
+
+ ```
+[rule "formatLinkSampleRule"]
+ event-type = comment-added
+ action = add-velocity-comment inline Comment for change ${its.formatLink($change-url, $change-number)} added.
+```
+
+[action-log-event]: #action-log-event
+### <a name="action-log-event">Action: log-event</a>
+
+The `log-event` action appends the event's properties to Gerrit's log.
+
+Logging happens at the info level per default, but can be overriden by
+adding the desired log level as parameter. Supported values are
+`error`, `warn`, `info`, and `debug`). So for example
+
+```
+ action = log-event error
+```
+
+appends the event's properties to Gerrit's log at error level. All
+other parameters are ignored.
+
+This action is useful, when testing rules or trying to refine
+conditions on rules, as it make the available properties visible.
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
diff --git a/src/main/resources/Documentation/config-rulebase-plugin-actions.md b/src/main/resources/Documentation/config-rulebase-plugin-actions.md
new file mode 100644
index 0000000..a0bbb50
--- /dev/null
+++ b/src/main/resources/Documentation/config-rulebase-plugin-actions.md
@@ -0,0 +1,11 @@
+@PLUGIN@-specific actions
+=========================
+
+@PLUGIN@ does not provide further specific actions. Only the [basic
+actions][basic-actions] are available.
+
+[basic-actions]: config-rulebase-common.html#actions
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
\ No newline at end of file
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
new file mode 100644
index 0000000..6830e56
--- /dev/null
+++ b/src/main/resources/Documentation/config.md
@@ -0,0 +1,22 @@
+Configuring @PLUGIN@
+====================
+
+Configuring @PLUGIN@ is a five step process:
+
+1. [Set up the ITS connectivity settings][config-connectivity]
+2. [Set up the general configuration][config-common]
+3. [Set up rule on how/what actions should be taken][config-rulebase-common]
+4. Restart gerrit, so the config changes take effect.
+5. Install the @PLUGIN@ jar in your gerrit site.
+
+[config-connectivity]: config-connectivity.html
+[config-common]: config-common.html
+[config-rulebase-common]: config-rulebase-common.html
+
+Done :-)
+
+
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
\ No newline at end of file
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/LoggingMockingTestCase.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/LoggingMockingTestCase.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/LoggingMockingTestCase.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/LoggingMockingTestCase.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/MockingTestCase.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/MockingTestCase.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/MockingTestCase.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/MockingTestCase.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/CollectionAppender.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/CollectionAppender.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/CollectionAppender.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/CollectionAppender.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/LogUtil.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/LogUtil.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/LogUtil.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/testutil/log/LogUtil.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractorTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractorTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractorTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyAttributeExtractorTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractorTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractorTest.java
similarity index 97%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractorTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractorTest.java
index dda4173..5ca50e9 100644
--- a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/hooks/util/PropertyExtractorTest.java
@@ -22,6 +22,7 @@
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.data.AccountAttribute;
import com.google.gerrit.server.data.ApprovalAttribute;
@@ -38,6 +39,7 @@
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.inject.Guice;
import com.google.inject.Injector;
+
import com.googlesource.gerrit.plugins.hooks.testutil.LoggingMockingTestCase;
import com.googlesource.gerrit.plugins.hooks.util.IssueExtractor;
import com.googlesource.gerrit.plugins.hooks.util.PropertyExtractor;
@@ -465,5 +467,24 @@
}
private class DummyChangeEvent extends ChangeEvent {
+ @SuppressWarnings("unused")
+ public String getType() {
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ public Project.NameKey getProjectNameKey() {
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ public Change.Key getChangeKey() {
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ public String getRefName() {
+ return null;
+ }
}
-}
\ No newline at end of file
+}
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java
similarity index 96%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java
index f3fbb12..7c65938 100644
--- a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java
@@ -86,7 +86,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("TestMessage")).andReturn(
new String[] {}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
replayMocks();
@@ -112,7 +111,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("TestMessage")).andReturn(
new String[] {}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
replayMocks();
@@ -142,7 +140,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711")).andReturn(
new String[] {"4711"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(true).atLeastOnce();
replayMocks();
@@ -168,7 +165,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711")).andReturn(
new String[] {"4711"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(true).atLeastOnce();
replayMocks();
@@ -194,7 +190,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711")).andReturn(
new String[] {"4711"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(false).atLeastOnce();
replayMocks();
@@ -224,7 +219,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711")).andReturn(
new String[] {"4711"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(false).atLeastOnce();
replayMocks();
@@ -255,7 +249,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42")).andReturn(
new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(true).atLeastOnce();
expect(itsFacade.exists("42")).andReturn(true).atLeastOnce();
@@ -283,7 +276,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42")).andReturn(
new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(true).atLeastOnce();
expect(itsFacade.exists("42")).andReturn(true).atLeastOnce();
@@ -311,7 +303,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42")).andReturn(
new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(false).atLeastOnce();
expect(itsFacade.exists("42")).andReturn(true).atLeastOnce();
@@ -345,7 +336,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42")).andReturn(
new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(false).atLeastOnce();
expect(itsFacade.exists("42")).andReturn(true).atLeastOnce();
@@ -377,7 +367,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42")).andReturn(
new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(false).atLeastOnce();
expect(itsFacade.exists("42")).andReturn(false).atLeastOnce();
@@ -411,7 +400,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42")).andReturn(
new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andReturn(false).atLeastOnce();
expect(itsFacade.exists("42")).andReturn(false).atLeastOnce();
@@ -443,7 +431,6 @@
expect(commit.getName()).andReturn("TestCommit").anyTimes();
expect(issueExtractor.getIssueIds("bug#4711, bug#42"))
.andReturn(new String[] {"4711", "42"}).atLeastOnce();
- expect(itsFacade.name()).andReturn("TestFacade").anyTimes();
expect(itsFacade.exists("4711")).andThrow(new IOException("InjectedEx1"))
.atLeastOnce();
expect(itsFacade.exists("42")).andReturn(false).atLeastOnce();
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ConditionTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ConditionTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ConditionTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ConditionTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/PropertyTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/PropertyTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/PropertyTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/PropertyTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBaseTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBaseTest.java
similarity index 74%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBaseTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBaseTest.java
index 2c6b466..b8d20d9 100644
--- a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBaseTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleBaseTest.java
@@ -218,16 +218,103 @@
assertEquals("Matched actionRequests do not match", expected, actual);
}
+ public void testWarnExistingFaultyNameRuleBaseFile() throws IOException {
+ injectRuleBase("", true);
+
+ replayMocks();
+
+ createRuleBase();
+
+ assertLogMessageContains("Please migrate"); // Migration warning for old name
+ assertLogMessageContains("does not exist"); // For global rule file at new name
+ }
+
+ public void testSimpleFaultyNameRuleBase() throws IOException {
+ injectRuleBase("[rule \"rule1\"]\n" +
+ "\tconditionA = value1\n" +
+ "\taction = action1", true);
+
+ Rule rule1 = createMock(Rule.class);
+ expect(ruleFactory.create("rule1")).andReturn(rule1);
+
+ Condition condition1 = createMock(Condition.class);
+ expect(conditionFactory.create("conditionA", "value1")).andReturn(condition1);
+ rule1.addCondition(condition1);
+
+ ActionRequest actionRequest1 = createMock(ActionRequest.class);
+ expect(actionRequestFactory.create("action1")).andReturn(actionRequest1);
+ rule1.addActionRequest(actionRequest1);
+
+ replayMocks();
+
+ createRuleBase();
+
+ assertLogMessageContains("Please migrate"); // Migration warning for old name
+ assertLogMessageContains("does not exist"); // For global rule file at new name
+ }
+
+ public void testGlobalRuleBaseFileAndFaultyNameFileAreLoaded() throws IOException {
+ injectRuleBase("[rule \"rule1\"]\n" +
+ "\taction = action1", false);
+
+ injectRuleBase("[rule \"rule2\"]\n" +
+ "\taction = action2", true);
+
+ Collection<Property> properties = Collections.emptySet();
+
+ Rule rule1 = createMock(Rule.class);
+ expect(ruleFactory.create("rule1")).andReturn(rule1);
+
+ ActionRequest actionRequest1 = createMock(ActionRequest.class);
+ expect(actionRequestFactory.create("action1")).andReturn(actionRequest1);
+ rule1.addActionRequest(actionRequest1);
+
+ List<ActionRequest> rule1Match = Lists.newArrayListWithCapacity(1);
+ rule1Match.add(actionRequest1);
+ expect(rule1.actionRequestsFor(properties)).andReturn(rule1Match);
+
+ Rule rule2 = createMock(Rule.class);
+ expect(ruleFactory.create("rule2")).andReturn(rule2);
+
+ ActionRequest actionRequest2 = createMock(ActionRequest.class);
+ expect(actionRequestFactory.create("action2")).andReturn(actionRequest2);
+ rule2.addActionRequest(actionRequest2);
+
+ List<ActionRequest> rule2Match = Lists.newArrayListWithCapacity(1);
+ rule1Match.add(actionRequest2);
+ expect(rule2.actionRequestsFor(properties)).andReturn(rule2Match);
+
+ replayMocks();
+
+ RuleBase ruleBase = createRuleBase();
+
+ Collection<ActionRequest> actual = ruleBase.actionRequestsFor(properties);
+
+ List<ActionRequest> expected = Lists.newArrayListWithCapacity(2);
+ expected.add(actionRequest1);
+ expected.add(actionRequest2);
+
+ assertEquals("Matched actionRequests do not match", expected, actual);
+
+ assertLogMessageContains("Please migrate"); // Migration warning for old name
+ }
+
private RuleBase createRuleBase() {
return injector.getInstance(RuleBase.class);
}
private void injectRuleBase(String rules) throws IOException {
+ injectRuleBase(rules, false);
+ }
+
+ private void injectRuleBase(String rules, Boolean faultyName) throws IOException {
File ruleBaseFile = new File(sitePath, "etc" + File.separatorChar + "its" +
- File.separator + "action.config");
+ File.separator + "action" + (faultyName ? "" : "s") + ".config");
File ruleBaseParentFile = ruleBaseFile.getParentFile();
- assertTrue("Failed to create parent (" + ruleBaseParentFile + ") for " +
- "rule base", ruleBaseParentFile.mkdirs());
+ if (!ruleBaseParentFile.exists()) {
+ assertTrue("Failed to create parent (" + ruleBaseParentFile + ") for " +
+ "rule base", ruleBaseParentFile.mkdirs());
+ }
FileWriter unbufferedWriter = new FileWriter(ruleBaseFile);
BufferedWriter writer = new BufferedWriter(unbufferedWriter);
writer.write(rules);
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/RuleTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddCommentTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddCommentTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddCommentTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityCommentTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityCommentTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddVelocityCommentTest.java
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEventTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEventTest.java
similarity index 100%
rename from its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEventTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/LogEventTest.java