| :linkattrs: | 
 | = Gerrit Code Review - Prolog Submit Rules Cookbook | 
 |  | 
 | [[SubmitRule]] | 
 | == Submit Rule | 
 | A _Submit Rule_ in Gerrit is logic that defines when a change is submittable. | 
 | By default, a change is submittable when it gets at least one | 
 | highest vote in each voting category and has no lowest vote (aka veto vote) in | 
 | any category.  Typically, this means that a change needs `Code-Review+2`, | 
 | `Verified+1` and has neither `Code-Review-2` nor `Verified-1` to become | 
 | submittable. | 
 |  | 
 | While this rule is a good default, there are projects which need more | 
 | flexibility for defining when a change is submittable.  In Gerrit, it is | 
 | possible to use Prolog based rules to provide project specific submit rules and | 
 | replace the default submit rules. Using Prolog based rules, project owners can | 
 | define a set of criteria which must be fulfilled for a change to become | 
 | submittable. For a change that is not submittable, the set of needed criteria | 
 | is displayed in the Gerrit UI. | 
 |  | 
 | [NOTE] | 
 | Loading and executing Prolog submit rules may be disabled by setting | 
 | `rules.enable=false` in the Gerrit config file (see | 
 | link:config-gerrit.html#_a_id_rules_a_section_rules[rules section]) | 
 |  | 
 | link:https://groups.google.com/d/topic/repo-discuss/wJxTGhlHZMM/discussion[This | 
 | discussion thread,role=external,window=_blank] explains why Prolog was chosen for the purpose of writing | 
 | project specific submit rules. | 
 | link:https://gerrit-documentation.storage.googleapis.com/ReleaseNotes/ReleaseNotes-2.2.2.html#_prolog[Gerrit | 
 | 2.2.2 ReleaseNotes,role=external,window=_blank] introduces Prolog support in Gerrit. | 
 |  | 
 | [[SubmitType]] | 
 | == Submit Type | 
 | A _Submit Type_ is a strategy that is used on submit to integrate the | 
 | change into the destination branch. Supported submit types are: | 
 |  | 
 | * `Fast Forward Only` | 
 | * `Merge If Necessary` | 
 | * `Merge Always` | 
 | * `Cherry Pick` | 
 | * `Rebase If Necessary` | 
 |  | 
 | _Submit Type_ is a project global setting. This means that the same submit type | 
 | is used for all changes of one project. | 
 |  | 
 | Projects which need more flexibility in choosing, or enforcing, a submit type | 
 | can use Prolog based submit type which replaces the project's default submit | 
 | type. | 
 |  | 
 | Prolog based submit type computes a submit type for each change. The computed | 
 | submit type is shown on the change screen for each change. | 
 |  | 
 | When submitting changes in a batch using "Submit including ancestors" or "Submit | 
 | whole topic", submit type rules may not be used to mix submit types on a single | 
 | branch, and trying to submit such a batch will fail. This avoids potentially | 
 | confusing behavior and spurious submit failures. It is recommended to only use | 
 | submit type rules to change submit types for an entire branch, which avoids this | 
 | situation. | 
 |  | 
 | == Prolog Language | 
 | This document is not a complete Prolog tutorial. | 
 | link:http://en.wikipedia.org/wiki/Prolog[This Wikipedia page on Prolog,role=external,window=_blank] is a | 
 | good starting point for learning the Prolog language. This document will only | 
 | explain some elements of Prolog that are necessary to understand the provided | 
 | examples. | 
 |  | 
 | == Prolog in Gerrit | 
 | Gerrit uses its own link:https://gerrit.googlesource.com/prolog-cafe/[fork,role=external,window=_blank] of the | 
 | original link:http://kaminari.istc.kobe-u.ac.jp/PrologCafe/[prolog-cafe,role=external,window=_blank] | 
 | project. Gerrit embeds the prolog-cafe library and can interpret Prolog programs | 
 | at runtime. | 
 |  | 
 | == Interactive Prolog Cafe Shell | 
 | For interactive testing and playing with Prolog, Gerrit provides the | 
 | link:pgm-prolog-shell.html[prolog-shell] program which opens an interactive | 
 | Prolog interpreter shell. | 
 |  | 
 | For batch or unit tests, see the examples in Gerrit source directory | 
 | link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/prologtests/examples/[prologtests/examples,role=external,window=_blank]. | 
 |  | 
 | [NOTE] | 
 | The interactive shell is just a prolog shell, it does not load | 
 | a gerrit server environment and thus is not intended for | 
 | xref:TestingSubmitRules[testing submit rules]. | 
 |  | 
 | == SWI-Prolog | 
 | Instead of using the link:pgm-prolog-shell.html[prolog-shell] program one can | 
 | also use the link:http://www.swi-prolog.org/[SWI-Prolog,role=external,window=_blank] environment. It | 
 | provides a better shell interface and a graphical source-level debugger. | 
 |  | 
 | [[RulesFile]] | 
 | == The rules.pl file | 
 | This section explains how to create and edit project specific submit rules. How | 
 | to actually write the submit rules is explained in the next section. | 
 |  | 
 | Project specific submit rules are stored in the `rules.pl` file in the | 
 | `refs/meta/config` branch of that project.  Therefore, we need to fetch and | 
 | checkout the `refs/meta/config` branch in order to create or edit the `rules.pl` | 
 | file: | 
 |  | 
 | ---- | 
 |   $ git fetch origin refs/meta/config:config | 
 |   $ git checkout config | 
 |   ... edit or create the rules.pl file | 
 |   $ git add rules.pl | 
 |   $ git commit -m "My submit rules" | 
 |   $ git push origin HEAD:refs/meta/config | 
 | ---- | 
 |  | 
 | [[HowToWriteSubmitRules]] | 
 | == How to write submit rules | 
 | Whenever Gerrit needs to evaluate submit rules for a change `C` from project `P` | 
 | it will first initialize the embedded Prolog interpreter by: | 
 |  | 
 | * consulting a set of facts about the change `C` | 
 | * consulting the `rules.pl` from the project `P` | 
 |  | 
 | Conceptually we can imagine that Gerrit adds a set of facts about the change | 
 | `C` on top of the `rules.pl` file and then consults it. The set of facts about | 
 | the change `C` will look like: | 
 |  | 
 | ---- | 
 |   :- package gerrit.                                                   <1> | 
 |  | 
 |   commit_author(user(1000000), 'John Doe', 'john.doe@example.com').    <2> | 
 |   commit_committer(user(1000000), 'John Doe', 'john.doe@example.com'). <3> | 
 |   commit_message('Add plugin support to Gerrit').                      <4> | 
 |   ... | 
 | ---- | 
 |  | 
 | <1> Gerrit will provide its facts in a package named `gerrit`. This means we | 
 | have to use qualified names when writing our code and referencing these facts. | 
 | For example: `gerrit:commit_author(ID, N, M)` | 
 | <2> user ID, full name and email address of the commit author | 
 | <3> user ID, full name and email address of the commit committer | 
 | <4> commit message | 
 |  | 
 | A complete set of facts which Gerrit provides about the change is listed in the | 
 | link:prolog-change-facts.html[Prolog Facts for Gerrit Change]. | 
 |  | 
 | By default, Gerrit will search for a `submit_rule/1` predicate in the `rules.pl` | 
 | file, evaluate the `submit_rule(X)` and then inspect the value of `X` in order | 
 | to decide whether the change is submittable or not and also to find the set of | 
 | needed criteria for the change to become submittable. This means that Gerrit has | 
 | an expectation on the format and value of the result of the `submit_rule` | 
 | predicate which is expected to be a `submit` term of the following format: | 
 |  | 
 | ---- | 
 |   submit(label(label-name, status) [, label(label-name, status)]*) | 
 | ---- | 
 |  | 
 | where `label-name` is usually `'Code-Review'` or `'Verified'` but could also | 
 | be any other string (see examples below). The `status` is one of: | 
 |  | 
 | * `ok(user(ID))`. This status is used to tell that this label/category has been | 
 |   met. | 
 | * `need(_)` is used to tell that this label/category is needed for the change to | 
 |   become submittable. | 
 | * `reject(user(ID))`. This status is used to tell that this label/category is | 
 |   blocking submission of the change. | 
 | * `impossible(_)` is used when the logic knows that the change cannot be submitted | 
 |   as-is. This is meant for cases where the logic requires members of a specific | 
 |   group to apply a specific label on a change, but no users are in that group. | 
 |   This is usually caused by misconfiguration of permissions. | 
 | * `may(_)` allows expression of approval categories that are optional, i.e. | 
 |   could either be set or unset without ever influencing whether the change | 
 |   could be submitted. | 
 |  | 
 | [NOTE] | 
 | For a change to be submittable all `label` terms contained in the returned | 
 | `submit` term must have either `ok` or `may` status. | 
 |  | 
 | [IMPORTANT] | 
 | Gerrit will let the Prolog engine continue searching for solutions of | 
 | the `submit_rule(X)` query until it finds the first one where all labels in the | 
 | return result have either status `ok` or `may` or there are no more solutions. | 
 | If a solution where all labels have status `ok` is found then all previously | 
 | found solutions are ignored. Otherwise, all labels names with status `need` | 
 | from all solutions will be displayed in the UI indicating the set of conditions | 
 | needed for the change to become submittable. | 
 |  | 
 | Here some examples of possible return values from the `submit_rule` predicate: | 
 |  | 
 | ---- | 
 |   submit(label('Code-Review', ok(user(ID))))                        <1> | 
 |   submit(label('Code-Review', ok(user(ID))), | 
 |       label('Verified', reject(user(ID))))                          <2> | 
 |   submit(label('Author-is-John-Doe', need(_))                       <3> | 
 | ---- | 
 |  | 
 | <1> label `'Code-Review'` is met. As there are no other labels in the | 
 |     return result, the change is submittable. | 
 | <2> label `'Verified'` is rejected. Change is not submittable. | 
 | <3> label `'Author-is-John-Doe'` is needed for the change to become submittable. | 
 |     Note that this tells nothing about how this criteria will be met. It is up | 
 |     to the implementer of the `submit_rule` to return | 
 |     `label('Author-is-John-Doe', ok(user(ID)))` when this criteria is met. Most | 
 |     likely, it will have to match against `gerrit:commit_author` in order to | 
 |     check if this criteria is met. This will become clear through the examples | 
 |     below. | 
 |  | 
 | Of course, when implementing the `submit_rule` we will use the facts about the | 
 | change that are already provided by Gerrit. | 
 |  | 
 | Another aspect of the return result from the `submit_rule` predicate is that | 
 | Gerrit uses it to decide which set of labels to display on the change review | 
 | screen for voting. If the return result contains label `'ABC'` and if the label | 
 | `'ABC'` is link:config-labels.html[defined for the project] then voting for the | 
 | label `'ABC'` will be displayed. Otherwise, it is not displayed. Note that the | 
 | project doesn't need a defined label for each label contained in the result of | 
 | `submit_rule` predicate.  For example, the decision whether | 
 | `'Author-is-John-Doe'` label is met will probably not be made by explicit voting | 
 | but, instead, by inspecting the facts about the change. | 
 |  | 
 | [[SubmitFilter]] | 
 | == Submit Filter | 
 | Another mechanism of changing the default submit rules is to implement the | 
 | `submit_filter/2` predicate. While Gerrit will search for the `submit_rule` only | 
 | in the `rules.pl` file of the current project, the `submit_filter` will be | 
 | searched for in the `rules.pl` of all parent projects of the current project, | 
 | but not in the `rules.pl` of the current project. The search will start from the | 
 | immediate parent of the current project, then in the parent project of that | 
 | project and so on until, and including, the `'All-Projects'` project. | 
 |  | 
 | The purpose of the submit filter is, as its name says, to filter the results | 
 | of the `submit_rule`. Therefore, the `submit_filter` predicate has two | 
 | parameters: | 
 |  | 
 | ---- | 
 |   submit_filter(In, Out) :- ... | 
 | ---- | 
 | Gerrit will invoke `submit_filter` with the `In` parameter containing a `submit` | 
 | structure produced by the `submit_rule` and will take the value of the `Out` | 
 | parameter as the result. | 
 |  | 
 | The `Out` value of a `submit_filter` will become the `In` value for the | 
 | next `submit_filter` in the parent line. The value of the `Out` parameter | 
 | of the top-most `submit_filter` is the final result of the submit rule that | 
 | is used to decide whether a change is submittable or not. | 
 |  | 
 | [IMPORTANT] | 
 | `submit_filter` is a mechanism for Gerrit administrators to implement | 
 | and enforce submit rules that would apply to all projects while `submit_rule` is | 
 | a mechanism for project owners to implement project specific submit rules. | 
 | However, project owners who own several projects could also make use of | 
 | `submit_filter` by using a common parent project for all their projects and | 
 | implementing the `submit_filter` in this common parent project. This way they | 
 | can avoid implementing the same `submit_rule` in all their projects. | 
 |  | 
 | The following "drawing" illustrates the order of the invocation and the chaining | 
 | of the results of the `submit_rule` and `submit_filter` predicates. | 
 | ---- | 
 |   All-Projects | 
 |   ^   submit_filter(B, S) :- ...  <4> | 
 |   | | 
 |   Parent-3 | 
 |   ^   <no submit filter here> | 
 |   | | 
 |   Parent-2 | 
 |   ^   submit_filter(A, B) :- ...  <3> | 
 |   | | 
 |   Parent-1 | 
 |   ^   submit_filter(X, A) :- ...  <2> | 
 |   | | 
 |   MyProject | 
 |       submit_rule(X) :- ...       <1> | 
 | ---- | 
 |  | 
 | <1> The `submit_rule` of `MyProject` is invoked first. | 
 | <2> The result `X` is filtered through the `submit_filter` from the `Parent-1` | 
 | project. | 
 | <3> The result of `submit_filter` from `Parent-1` project is filtered by the | 
 | `submit_filter` in the `Parent-2` project. Since `Parent-3` project doesn't have | 
 | a `submit_filter` it is skipped. | 
 | <4> The result of `submit_filter` from `Parent-2` project is filtered by the | 
 | `submit_filter` in the `All-Projects` project. The value in `S` is the final | 
 | value of the submit rule evaluation. | 
 |  | 
 | [NOTE] | 
 | If `MyProject` doesn't define its own `submit_rule` Gerrit will invoke the | 
 | default implementation of submit rule that is named `gerrit:default_submit` and | 
 | its result will be filtered as described above. | 
 |  | 
 | [[HowToWriteSubmitType]] | 
 | == How to write submit type | 
 | Writing custom submit type logic in Prolog is similar to | 
 | xref:HowToWriteSubmitRules[writing submit rules]. The only difference is that | 
 | one has to implement a `submit_type` predicate (instead of the `submit_rule`) | 
 | and that the return result of the `submit_type` has to be an atom that | 
 | represents one of the supported submit types: | 
 |  | 
 | * `fast_forward_only` | 
 | * `merge_if_necessary` | 
 | * `merge_always` | 
 | * `cherry_pick` | 
 | * `rebase_if_necessary` | 
 |  | 
 | == Submit Type Filter | 
 | Submit type filter works the same way as the xref:SubmitFilter[Submit Filter] | 
 | where the name of the filter predicate is `submit_type_filter`. | 
 |  | 
 | ---- | 
 |   submit_type_filter(In, Out). | 
 | ---- | 
 |  | 
 | Gerrit will invoke `submit_type_filter` with the `In` parameter containing a | 
 | result of the `submit_type` and will take the value of the `Out` parameter as | 
 | the result. | 
 |  | 
 | [[TestingSubmitRules]] | 
 | == Testing submit rules | 
 | The prolog environment running the `submit_rule` is loaded with state describing | 
 | the change that is being evaluated. The easiest way to load this state is to | 
 | test your `submit_rule` against a real change on a running gerrit instance. The | 
 | command link:cmd-test-submit-rule.html[test-submit rule] loads a specific change | 
 | and executes the `submit_rule`. It optionally reads the rule from from `stdin` | 
 | to facilitate easy testing. | 
 |  | 
 | ---- | 
 |   $ cat rules.pl | ssh gerrit_srv gerrit test-submit rule I45e080b105a50a625cc8e1fb5b357c0bfabe6d68 -s | 
 | ---- | 
 |  | 
 | == Prolog vs Gerrit plugin for project specific submit rules | 
 | Since version 2.5 Gerrit supports plugins and extension points. A plugin or an | 
 | extension point could also be used as another means to provide custom submit | 
 | rules. One could ask for a guideline when to use Prolog based submit rules and | 
 | when to go for writing a new plugin. Writing a Prolog program is usually much | 
 | faster than writing a Gerrit plugin. Prolog based submit rules can be pushed | 
 | to a project by project owners while Gerrit plugins could only be installed by | 
 | Gerrit administrators. In addition, Prolog based submit rules can be pushed | 
 | for review by pushing to `refs/for/refs/meta/config` branch. | 
 |  | 
 | On the other hand, Prolog based submit rules get a limited amount of facts about | 
 | the change exposed to them. Gerrit plugins get full access to Gerrit internals | 
 | and can potentially check more things than Prolog based rules. | 
 |  | 
 | From version 2.6 Gerrit plugins can contribute Prolog predicates. This way, we | 
 | can make use of the plugin provided predicates when writing Prolog based rules. | 
 |  | 
 | == Examples - Submit Rule | 
 | The following examples should serve as a cookbook for developing own submit | 
 | rules. Some of them are too trivial to be used in production and their only | 
 | purpose is to provide step by step introduction and understanding. | 
 |  | 
 | Some of the examples will implement the `submit_rule` and some will implement | 
 | the `submit_filter` just to show both possibilities.  Remember that | 
 | `submit_rule` is only invoked from the current project and `submit_filter` is | 
 | invoked from all parent projects. This is the most important fact in deciding | 
 | whether to implement `submit_rule` or `submit_filter`. | 
 |  | 
 | === Example 1: Make every change submittable | 
 | Let's start with a most trivial example where we would make every change | 
 | submittable regardless of the votes it has: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(W)) :- | 
 |     W = label('Any-Label-Name', ok(user(1000000))). | 
 | ---- | 
 |  | 
 | In this case we make no use of facts about the change. We don't need it as we | 
 | are simply making every change submittable. Note that, in this case, the Gerrit | 
 | UI will not show the UI for voting for the standard `'Code-Review'` and | 
 | `'Verified'` categories as labels with these names are not part of the return | 
 | result. The `'Any-Label-Name'` could really be any string. | 
 |  | 
 | The `user(1000000)` represents the user whose account ID is `1000000`. | 
 |  | 
 | [NOTE] | 
 | Instead of the account ID `1000000` we could have used any other account ID. | 
 | The following examples will use `user(ID)` instead of `user(1000000)` because | 
 | it is easier to read and doesn't suggest that there is anything special with | 
 | the account ID `1000000`. | 
 |  | 
 | === Example 2: Every change submittable and voting in the standard categories possible | 
 | This is continuation of the previous example where, in addition, to making | 
 | every change submittable we want to enable voting in the standard | 
 | `'Code-Review'` and `'Verified'` categories. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR, V)) :- | 
 |     CR = label('Code-Review', ok(user(ID))), | 
 |     V = label('Verified', ok(user(ID))). | 
 | ---- | 
 |  | 
 | Since for every change all label statuses are `'ok'` every change will be | 
 | submittable. Voting in the standard labels will be shown in the UI as the | 
 | standard label names are included in the return result. | 
 |  | 
 | === Example 3: Nothing is submittable | 
 | This example shows how to make all changes non-submittable regardless of the | 
 | votes they have. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(R)) :- | 
 |     R = label('Any-Label-Name', reject(user(ID))). | 
 | ---- | 
 |  | 
 | Since for any change we return only one label with status `reject`, no change | 
 | will be submittable. The UI will, however, not indicate what is needed for a | 
 | change to become submittable as we return no labels with status `need`. | 
 |  | 
 | === Example 4: Nothing is submittable but UI shows several 'Need ...' criteria | 
 | In this example no change is submittable but here we show how to present 'Need | 
 | <label>' information to the user in the UI. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | % In the UI this will show: Need Any-Label-Name | 
 | submit_rule(submit(N)) :- | 
 |     N = label('Any-Label-Name', need(_)). | 
 |  | 
 | % We could define more "need" labels by adding more rules | 
 | submit_rule(submit(N)) :- | 
 |     N = label('Another-Label-Name', need(_)). | 
 |  | 
 | % or by providing more than one need label in the same rule | 
 | submit_rule(submit(NX, NY)) :- | 
 |     NX = label('X-Label-Name', need(_)), | 
 |     NY = label('Y-Label-Name', need(_)). | 
 | ---- | 
 |  | 
 | In the UI this will show: | 
 |  | 
 | * `Need Any-Label-Name` | 
 | * `Need Another-Label-Name` | 
 | * `Need X-Label-Name` | 
 | * `Need Y-Label-Name` | 
 |  | 
 | From the example above we can see a few more things: | 
 |  | 
 | * comment in Prolog starts with the `%` character | 
 | * there could be multiple `submit_rule` predicates. Since Prolog, by default, | 
 |   tries to find all solutions for a query, the result will be union of all | 
 |   solutions. Therefore, we see all 4 `need` labels in the UI. | 
 |  | 
 | === Example 5: The 'Need ...' labels not shown when change is submittable | 
 | This example shows that, when there is a solution for `submit_rule(X)` where all | 
 | labels have status `ok` then Gerrit will not show any labels with the `need` | 
 | status from any of the previous `submit_rule(X)` solutions. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(N)) :- | 
 |     N = label('Some-Condition', need(_)). | 
 |  | 
 | submit_rule(submit(OK)) :- | 
 |     OK = label('Another-Condition', ok(user(ID))). | 
 | ---- | 
 |  | 
 | The `'Need Some-Condition'` will not be shown in the UI because of the result of | 
 | the second rule. | 
 |  | 
 | The same is valid if the two rules are swapped: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(OK)) :- | 
 |     OK = label('Another-Condition', ok(user(ID))). | 
 |  | 
 | submit_rule(submit(N)) :- | 
 |     N = label('Some-Condition', need(_)). | 
 | ---- | 
 |  | 
 | The result of the first rule will stop search for any further solutions. | 
 |  | 
 | === Example 6: Make change submittable if commit author is "John Doe" | 
 | This is the first example where we will use the Prolog facts about a change that | 
 | are automatically exposed by Gerrit. Our goal is to make any change submittable | 
 | when the commit author is named `'John Doe'`. In the very first | 
 | step let's make sure Gerrit UI shows `'Need Author-is-John-Doe'` in | 
 | the UI to clearly indicate to the user what is needed for a change to become | 
 | submittable: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Author)) :- | 
 |     Author = label('Author-is-John-Doe', need(_)). | 
 | ---- | 
 |  | 
 | This will show: | 
 |  | 
 | * `Need Author-is-John-Doe` | 
 |  | 
 | in the UI but no change will be submittable yet. Let's add another rule: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Author)) :- | 
 |     Author = label('Author-is-John-Doe', need(_)). | 
 |  | 
 | submit_rule(submit(Author)) :- | 
 |     gerrit:commit_author(A, 'John Doe', _), | 
 |     Author = label('Author-is-John-Doe', ok(A)). | 
 | ---- | 
 |  | 
 | In the second rule we return `ok` status for the `'Author-is-John-Doe'` label | 
 | if there is a `commit_author` fact where the full name is `'John Doe'`. If | 
 | author of a change is `'John Doe'` then the second rule will return a solution | 
 | where all labels have `ok` status and the change will become submittable. If | 
 | author of a change is not `'John Doe'` then only the first rule will produce a | 
 | solution. The UI will show `'Need Author-is-John-Doe'` but, as expected, the | 
 | change will not be submittable. | 
 |  | 
 | Instead of checking by full name we could also check by the email address: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Author)) :- | 
 |     Author = label('Author-is-John-Doe', need(_)). | 
 |  | 
 | submit_rule(submit(Author)) :- | 
 |     gerrit:commit_author(_, _, 'john.doe@example.com'), | 
 |     gerrit:uploader(U), | 
 |     Author = label('Author-is-John-Doe', ok(U)). | 
 | ---- | 
 |  | 
 | or by user id (assuming it is `1000000`): | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Author)) :- | 
 |     Author = label('Author-is-John-Doe', need(_)). | 
 |  | 
 | submit_rule(submit(Author)) :- | 
 |     U = user(1000000), | 
 |     gerrit:commit_author(U, _, _), | 
 |     Author = label('Author-is-John-Doe', ok(U)). | 
 | ---- | 
 |  | 
 | or by a combination of these 3 attributes: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Author)) :- | 
 |     Author = label('Author-is-John-Doe', need(_)). | 
 |  | 
 | submit_rule(submit(Author)) :- | 
 |     gerrit:commit_author(_, 'John Doe', 'john.doe@example.com'), | 
 |     gerrit:uploader(U), | 
 |     Author = label('Author-is-John-Doe', ok(U)). | 
 | ---- | 
 |  | 
 | === Example 7: Make change submittable if commit message starts with "Fix " | 
 | Besides showing how to make use of the commit message text the purpose of this | 
 | example is also to show how to match only a part of a string symbol. Similarly | 
 | like commit author the commit message is provided as a string symbol which is | 
 | an atom in Prolog terms. When working with an atom we could only match against | 
 | the whole value. To match only part of a string symbol we have, at least, two | 
 | options: | 
 |  | 
 | * convert the string symbol into a list of characters and then perform | 
 |   the "classical" list matching | 
 | * use the `regex_matches/2` or, even more convenient, the | 
 |   `gerrit:commit_message_matches/1` predicate | 
 |  | 
 | Let's implement both options: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Fix)) :- | 
 |     Fix = label('Commit-Message-starts-with-Fix', need(_)). | 
 |  | 
 | submit_rule(submit(Fix)) :- | 
 |     gerrit:commit_message(M), name(M, L), starts_with(L, "Fix "), | 
 |     gerrit:uploader(U), | 
 |     Fix = label('Commit-Message-starts-with-Fix', ok(U)). | 
 |  | 
 | starts_with(L, []). | 
 | starts_with([H|T1], [H|T2]) :- starts_with(T1, T2). | 
 | ---- | 
 |  | 
 | [NOTE] | 
 | The `name/2` embedded predicate is used to convert a string symbol into a | 
 | list of characters. A string `abc` is converted into a list of characters `[97, | 
 | 98, 99]`.  A double quoted string in Prolog is just a shortcut for creating a | 
 | list of characters. `"abc"` is a shortcut for `[97, 98, 99]`. This is why we use | 
 | double quotes for the `"Trivial Fix"` in the example above. | 
 |  | 
 | The `starts_with` predicate is self explaining. | 
 |  | 
 | Using the `gerrit:commit_message_matches` predicate is probably more efficient: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Fix)) :- | 
 |     Fix = label('Commit-Message-starts-with-Fix', need(_)). | 
 |  | 
 | submit_rule(submit(Fix)) :- | 
 |     gerrit:commit_message_matches('^Fix '), | 
 |     gerrit:uploader(U), | 
 |     Fix = label('Commit-Message-starts-with-Fix', ok(U)). | 
 | ---- | 
 |  | 
 | The previous example could also be written so that it first checks if the commit | 
 | message starts with 'Fix '. If true then it sets OK for that category and stops | 
 | further backtracking by using the cut `!` operator: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(Fix)) :- | 
 |     gerrit:commit_message_matches('^Fix '), | 
 |     gerrit:uploader(U), | 
 |     Fix = label('Commit-Message-starts-with-Fix', ok(U)), | 
 |     !. | 
 |  | 
 | % Message does not start with 'Fix ' so Fix is needed to submit | 
 | submit_rule(submit(Fix)) :- | 
 |     Fix = label('Commit-Message-starts-with-Fix', need(_)). | 
 | ---- | 
 |  | 
 | == The default submit policy | 
 | All examples until now concentrate on one particular aspect of change data. | 
 | However, in real-life scenarios we would rather want to reuse Gerrit's default | 
 | submit policy and extend/change it for our specific purpose.  This could be | 
 | done in one of the following ways: | 
 |  | 
 | * understand how the default submit policy is implemented and use that as a | 
 |   template for implementing custom submit rules, | 
 | * invoke the default submit rule implementation and then perform further | 
 |   actions on its return result. | 
 |  | 
 | === Default submit rule implementation | 
 | The default submit rule with the two default categories, `Code-Review` and | 
 | `Verified`, can be implemented as: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(V, CR)) :- | 
 |     gerrit:max_with_block(-2, 2, 'Code-Review', CR), | 
 |     gerrit:max_with_block(-1, 1, 'Verified', V). | 
 | ---- | 
 |  | 
 | Once this implementation is understood it can be customized to implement | 
 | project specific submit rules. Note, that this implementation hardcodes | 
 | the two default categories. Introducing a new category in the database would | 
 | require introducing the same category here or a `submit_filter` in a parent | 
 | project would have to care about including the new category in the result of | 
 | this `submit_rule`. On the other side, this example is easy to read and | 
 | understand. | 
 |  | 
 | === Reusing the default submit policy | 
 | To get results of Gerrit's default submit policy we use the | 
 | `gerrit:default_submit` predicate.  The `gerrit:default_submit(X)` includes all | 
 | categories from the database.  This means that if we write a submit rule like | 
 | this: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(X) :- gerrit:default_submit(X). | 
 | ---- | 
 |  | 
 | it is equivalent to not using `rules.pl` at all. We just delegate to | 
 | default logic. However, once we invoke the `gerrit:default_submit(X)` we can | 
 | perform further actions on the return result `X` and apply our specific | 
 | logic. The following pattern illustrates this technique: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(S) :- gerrit:default_submit(R), project_specific_policy(R, S). | 
 |  | 
 | project_specific_policy(R, S) :- ... | 
 | ---- | 
 |  | 
 | In the following examples both styles will be shown. | 
 |  | 
 | [[NonAuthorCodeReview]] | 
 | === Example 8: Make change submittable only if `Code-Review+2` is given by a non author | 
 | In this example we introduce a new label `Non-Author-Code-Review` and make it | 
 | satisfied if there is at least one `Code-Review+2` from a non author. All other | 
 | default policies like the `Verified` category and vetoing changes still apply. | 
 |  | 
 | ==== Reusing the `gerrit:default_submit` | 
 | First, we invoke `gerrit:default_submit` to compute the result for the default | 
 | submit policy and then add the `Non-Author-Code-Review` label to it.  The | 
 | `Non-Author-Code-Review` label is added with status `ok` if such an approval | 
 | exists or with status `need` if it doesn't exist. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(S) :- | 
 |     gerrit:default_submit(X), | 
 |     X =.. [submit | Ls], | 
 |     add_non_author_approval(Ls, R), | 
 |     S =.. [submit | R]. | 
 |  | 
 | add_non_author_approval(S1, S2) :- | 
 |     gerrit:commit_author(A), | 
 |     gerrit:commit_label(label('Code-Review', 2), R), | 
 |     R \= A, !, | 
 |     S2 = [label('Non-Author-Code-Review', ok(R)) | S1]. | 
 | add_non_author_approval(S1, [label('Non-Author-Code-Review', need(_)) | S1]). | 
 | ---- | 
 |  | 
 | This example uses the `univ` operator `=..` to "unpack" the result of the | 
 | default_submit, which is a structure of the form `submit(label('Code-Review', | 
 | ok(user(ID))), label('Verified', need(_)), ...)` into a list like `[submit, | 
 | label('Code-Review', ok(user(ID))), label('Verified', need(_)), ...]`.  Then we | 
 | process the tail of the list (the list of labels) as a Prolog list, which is | 
 | much easier than processing a structure. In the end we use the same `univ` | 
 | operator to convert the resulting list of labels back into a `submit` structure | 
 | which is expected as a return result. The `univ` operator works both ways. | 
 |  | 
 | In `add_non_author_approval` we use the `cut` operator `!` to prevent Prolog | 
 | from searching for more solutions once the `cut` point is reached. This is | 
 | important because in the second `add_non_author_approval` rule we just add the | 
 | `label('Non-Author-Code-Review', need(_))` without first checking that there | 
 | is no non author `Code-Review+2`. The second rule will only be reached | 
 | if the `cut` in the first rule is not reached and it only happens if a | 
 | predicate before the `cut` fails. | 
 |  | 
 | This fact can be bypassed by users who have | 
 | link:access-control.html#category_forge_author[Forge Author] permission. | 
 |  | 
 | ==== Don't use `gerrit:default_submit` | 
 | Let's implement the same submit rule the other way, without reusing the | 
 | `gerrit:default_submit`: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR, V)) :- | 
 |     base(CR, V), | 
 |     CR = label(_, ok(Reviewer)), | 
 |     gerrit:commit_author(Author), | 
 |     Author \= Reviewer, | 
 |     !. | 
 |  | 
 | submit_rule(submit(CR, V, N)) :- | 
 |     base(CR, V), | 
 |     N = label('Non-Author-Code-Review', need(_)). | 
 |  | 
 | base(CR, V) :- | 
 |     gerrit:max_with_block(-2, 2, 'Code-Review', CR), | 
 |     gerrit:max_with_block(-1, 1, 'Verified', V). | 
 | ---- | 
 |  | 
 | The latter implementation is probably easier to understand and the code looks | 
 | cleaner. Note, however, that the latter implementation will always return the | 
 | two standard categories only (`Code-Review` and `Verified`) even if a new | 
 | category has been inserted into the database. To include the new category | 
 | the `rules.pl` would need to be modified or a `submit_filter` in a parent | 
 | project would have to care about including the new category in the result | 
 | of this `submit_rule`. | 
 |  | 
 | The former example, however, would include any newly added category as it | 
 | invokes the `gerrit:default_submit` and then modifies its result. | 
 |  | 
 | Which of these two behaviors is desired will always depend on how a particular | 
 | Gerrit server is managed. | 
 |  | 
 | === Example 9: Remove the `Verified` category | 
 | A project has no build and test. It consists of only text files and needs only | 
 | code review.  We want to remove the `Verified` category from this project so | 
 | that `Code-Review+2` is the only criteria for a change to become submittable. | 
 | We also want the UI to not show the `Verified` category in the table with | 
 | votes and on the voting screen. | 
 |  | 
 | This is quite simple without reusing the `gerrit:default_submit`: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR)) :- | 
 |     gerrit:max_with_block(-2, 2, 'Code-Review', CR). | 
 | ---- | 
 |  | 
 | Implementing the same rule by reusing `gerrit:default_submit` is a bit more complex: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(S) :- | 
 |     gerrit:default_submit(X), | 
 |     X =.. [submit | Ls], | 
 |     remove_verified_category(Ls, R), | 
 |     S =.. [submit | R]. | 
 |  | 
 | remove_verified_category([], []). | 
 | remove_verified_category([label('Verified', _) | T], R) :- remove_verified_category(T, R), !. | 
 | remove_verified_category([H|T], [H|R]) :- remove_verified_category(T, R). | 
 | ---- | 
 |  | 
 | === Example 10: Combine examples 8 and 9 | 
 | In this example we want to both remove the verified and have the four eyes | 
 | principle.  This means we want a combination of examples 8 and 9. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(S) :- | 
 |     gerrit:default_submit(X), | 
 |     X =.. [submit | Ls], | 
 |     remove_verified_category(Ls, R1), | 
 |     add_non_author_approval(R1, R), | 
 |     S =.. [submit | R]. | 
 | ---- | 
 |  | 
 | The `remove_verified_category` and `add_non_author_approval` predicates are the | 
 | same as defined in the previous two examples. | 
 |  | 
 | Without reusing the `gerrit:default_submit` the same example may be implemented | 
 | as: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR)) :- | 
 |     base(CR), | 
 |     CR = label(_, ok(Reviewer)), | 
 |     gerrit:commit_author(Author), | 
 |     Author \= Reviewer, | 
 |     !. | 
 |  | 
 | submit_rule(submit(CR, N)) :- | 
 |     base(CR), | 
 |     N = label('Non-Author-Code-Review', need(_)). | 
 |  | 
 | base(CR) :- | 
 |     gerrit:max_with_block(-2, 2, 'Code-Review', CR). | 
 | ---- | 
 |  | 
 | === Example 11: Remove the `Verified` category from all projects | 
 | Example 9, implements `submit_rule` that removes the `Verified` category from | 
 | one project. In this example we do the same but we want to remove the `Verified` | 
 | category from all projects. This means we have to implement `submit_filter` and | 
 | we have to do that in the `rules.pl` of the `All-Projects` project. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_filter(In, Out) :- | 
 |     In =.. [submit | Ls], | 
 |     remove_verified_category(Ls, R), | 
 |     Out =.. [submit | R]. | 
 |  | 
 | remove_verified_category([], []). | 
 | remove_verified_category([label('Verified', _) | T], R) :- remove_verified_category(T, R), !. | 
 | remove_verified_category([H|T], [H|R]) :- remove_verified_category(T, R). | 
 | ---- | 
 |  | 
 | === Example 12: On release branches require DrNo in addition to project rules | 
 | A new category 'DrNo' is added to the database and is required for release | 
 | branches. To mark a branch as a release branch we use | 
 | `drno('refs/heads/branch')`. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | drno('refs/heads/master'). | 
 | drno('refs/heads/stable-2.3'). | 
 | drno('refs/heads/stable-2.4'). | 
 | drno('refs/heads/stable-2.5'). | 
 | drno('refs/heads/stable-2.5'). | 
 |  | 
 | submit_filter(In, Out) :- | 
 |     gerrit:change_branch(Branch), | 
 |     drno(Branch), | 
 |     !, | 
 |     In =.. [submit | I], | 
 |     gerrit:max_with_block(-1, 1, 'DrNo', DrNo), | 
 |     Out =.. [submit, DrNo | I]. | 
 |  | 
 | submit_filter(In, Out) :- In = Out. | 
 | ---- | 
 |  | 
 | === Example 13: 1+1=2 Code-Review | 
 | In this example we introduce accumulative voting to determine if a change is | 
 | submittable or not. We modify the standard `Code-Review` to be accumulative, and | 
 | make the change submittable if the total score is `2` or higher. | 
 |  | 
 | The code in this example is very similar to Example 8, with the addition of | 
 | `findall/3` and `gerrit:remove_label`. | 
 |  | 
 | The `findall/3` embedded predicate is used to form a list of all objects that | 
 | satisfy a specified Goal. In this example it is used to get a list of all the | 
 | `Code-Review` scores. `gerrit:remove_label` is a built-in helper that is | 
 | implemented similarly to the `remove_verified_category` as seen in the previous | 
 | example. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | sum_list([], 0). | 
 | sum_list([H | Rest], Sum) :- sum_list(Rest,Tmp), Sum is H + Tmp. | 
 |  | 
 | add_category_min_score(In, Category, Min,  P) :- | 
 |     findall(X, gerrit:commit_label(label(Category,X),R),Z), | 
 |     sum_list(Z, Sum), | 
 |     Sum >= Min, !, | 
 |     gerrit:commit_label(label(Category, V), U), | 
 |     V >= 1, | 
 |     !, | 
 |     P = [label(Category,ok(U)) | In]. | 
 |  | 
 | add_category_min_score(In, Category,Min,P) :- | 
 |     P = [label(Category,need(Min)) | In]. | 
 |  | 
 | submit_rule(S) :- | 
 |     gerrit:default_submit(X), | 
 |     X =.. [submit | Ls], | 
 |     gerrit:remove_label(Ls,label('Code-Review',_),NoCR), | 
 |     add_category_min_score(NoCR,'Code-Review', 2, Labels), | 
 |     S =.. [submit | Labels]. | 
 | ---- | 
 |  | 
 | Implementing the same example without using `gerrit:default_submit`: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR, V)) :- | 
 |     sum(2, 'Code-Review', CR), | 
 |     gerrit:max_with_block(-1, 1, 'Verified', V). | 
 |  | 
 | % Sum the votes in a category. Uses a helper function score/2 | 
 | % to select out only the score values the given category. | 
 | sum(VotesNeeded, Category, label(Category, ok(_))) :- | 
 |     findall(Score, score(Category, Score), All), | 
 |     sum_list(All, Sum), | 
 |     Sum >= VotesNeeded, | 
 |     !. | 
 | sum(VotesNeeded, Category, label(Category, need(VotesNeeded))). | 
 |  | 
 | score(Category, Score) :- | 
 |     gerrit:commit_label(label(Category, Score), User). | 
 |  | 
 | % Simple Prolog routine to sum a list of integers. | 
 | sum_list(List, Sum)   :- sum_list(List, 0, Sum). | 
 | sum_list([X|T], Y, S) :- Z is X + Y, sum_list(T, Z, S). | 
 | sum_list([], S, S). | 
 | ---- | 
 |  | 
 | === Example 14: Mentor and Mentee | 
 | The mentor and mentee example allow you to specify a user (the `mentor`) | 
 | that must approve all changes done by another user (the `mentee`). | 
 |  | 
 | The code first checks if the commit author is in the apprentice database. | 
 | If the commit is done by a `mentee`, it will check if there is a `+2` | 
 | review by the associated `mentor`. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | % mentor_mentee(Mentor, Mentee). | 
 | % Extend this with appropriate user-id for your mentor/mentee setup. | 
 | mentor_mentee(user(1000064), user(1000000)). | 
 |  | 
 | submit_rule(S) :- | 
 |     gerrit:default_submit(In), | 
 |     In =.. [submit | Ls], | 
 |     add_mentee_mentor(Ls, R), | 
 |     S =.. [submit | R]. | 
 |  | 
 | check_mentor_approval(S1, S2, Mentor) :- | 
 |     gerrit:commit_label(label('Code-Review', 2), R), | 
 |     R = Mentor, !, | 
 |     S2 = [label('Mentor-Approval', ok(R)) | S1]. | 
 | check_mentor_approval(S1, [label('Mentor-Approval', need(_)) | S1], _). | 
 |  | 
 | add_mentee_mentor(S1, S2) :- | 
 |     gerrit:commit_author(Id), | 
 |     mentor_mentee(Mentor, Id), | 
 |     !, | 
 |     check_mentor_approval(S1, S2, Mentor). | 
 |  | 
 | add_mentee_mentor(S, S). | 
 | ---- | 
 |  | 
 | === Example 15: Make change submittable if all comments have been resolved | 
 | In this example we will use the `unresolved_comments_count` fact about a | 
 | change. Our goal is to block the submission of any change with some | 
 | unresolved comments. Basically, it can be achieved by the following rules: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(R)) :- | 
 |     gerrit:unresolved_comments_count(0), | 
 |     !, | 
 |     gerrit:uploader(U), | 
 |     R = label('All-Comments-Resolved', ok(U)). | 
 |  | 
 | submit_rule(submit(R)) :- | 
 |     gerrit:unresolved_comments_count(U), | 
 |     U > 0, | 
 |     R = label('All-Comments-Resolved', need(_)). | 
 | ---- | 
 |  | 
 | Suppose currently a change is submittable if it gets `+2` for `Code-Review` | 
 | and `+1` for `Verified`. It can be extended to support the above rules as | 
 | follows: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR, V, R)) :- | 
 |     base(CR, V), | 
 |     gerrit:unresolved_comments_count(0), | 
 |     !, | 
 |     gerrit:uploader(U), | 
 |     R = label('All-Comments-Resolved', ok(U)). | 
 |  | 
 | submit_rule(submit(CR, V, R)) :- | 
 |     base(CR, V), | 
 |     gerrit:unresolved_comments_count(U), | 
 |     U > 0, | 
 |     R = label('All-Comments-Resolved', need(_)). | 
 |  | 
 | base(CR, V) :- | 
 |     gerrit:max_with_block(-2, 2, 'Code-Review', CR), | 
 |     gerrit:max_with_block(-1, 1, 'Verified', V). | 
 | ---- | 
 |  | 
 | Note that a new label as `All-Comments-Resolved` should not be configured. | 
 | It's only used to show `'Needs All-Comments-Resolved'` in the UI to clearly | 
 | indicate to the user that all the comments have to be resolved for the | 
 | change to become submittable. | 
 |  | 
 | === Example 16: Make change submittable if it is a pure revert | 
 | In this example we will use the `pure_revert` fact about a | 
 | change. Our goal is to block the submission of any change that is not a | 
 | pure revert. Basically, it can be achieved by the following rules: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(R)) :- | 
 |     gerrit:pure_revert(1), | 
 |     !, | 
 |     gerrit:uploader(U), | 
 |     R = label('Is-Pure-Revert', ok(U)). | 
 |  | 
 | submit_rule(submit(label('Is-Pure-Revert', need(_)))). | 
 | ---- | 
 |  | 
 | Suppose currently a change is submittable if it gets `+2` for `Code-Review` | 
 | and `+1` for `Verified`. It can be extended to support the above rules as | 
 | follows: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(CR, V, R)) :- | 
 |   base(CR, V), | 
 |   set_pure_revert_label(R). | 
 |  | 
 | base(CR, V) :- | 
 |   gerrit:max_with_block(-2, 2, 'Code-Review', CR), | 
 |   gerrit:max_with_block(-1, 1, 'Verified', V). | 
 |  | 
 | set_pure_revert_label(R) :- | 
 |   gerrit:pure_revert(1), | 
 |   !, | 
 |   gerrit:uploader(U), | 
 |   R = label('Is-Pure-Revert', ok(U)). | 
 |  | 
 | set_pure_revert_label(label('Is-Pure-Revert', need(_))). | 
 | ---- | 
 |  | 
 | Note that a new label as `Is-Pure-Revert` should not be configured. | 
 | It's only used to show `'Needs Is-Pure-Revert'` in the UI to clearly | 
 | indicate to the user that the change has to be a pure revert in order | 
 | to become submittable. | 
 |  | 
 | === Example 17: Make a change submittable if it doesn't include specific files | 
 |  | 
 | We can block any change which contains a submodule file change: | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_rule(submit(R)) :- | 
 |   gerrit:includes_file(file(_,_,'SUBMODULE')), | 
 |   !, | 
 |   R = label('All-Submodules-Resolved', need(_)). | 
 | submit_rule(submit(label('All-Submodules-Resolved', ok(A)))) :- | 
 |   gerrit:commit_author(A). | 
 | ---- | 
 |  | 
 | We can also block specific files, modification type, or file type, | 
 | by changing include_files/1 to a different parameter. E.g, | 
 | include_files('a.txt',_,_) includes any update to "a.txt", and | 
 | ('a.txt','D',_) includes any deletion to "a.txt". Also, (_,_,_) includes | 
 | any file (other than magic file). | 
 |  | 
 | An inclusive list of possible arguments using the code above with variations | 
 | of include_file: | 
 | The first parameter is the file name. | 
 | The second is the modification type ('A' for 'added', 'M' for 'modified', | 
 | 'D' for 'deleted', 'R' for 'renamed', 'C' for 'COPIED' and 'W' for 'rewrite'). | 
 | The third argument is the type of file, with the options being a submodule | 
 | file 'SUBMODULE' and a non-submodule file being 'REGULAR'. | 
 |  | 
 | == Examples - Submit Type | 
 | The following examples show how to implement own submit type rules. | 
 |  | 
 | === Example 1: Set a `Cherry Pick` submit type for all changes | 
 | This example sets the `Cherry Pick` submit type for all changes. It overrides | 
 | whatever is set as project default submit type. | 
 |  | 
 | rules.pl | 
 | [source,prolog] | 
 | ---- | 
 | submit_type(cherry_pick). | 
 | ---- | 
 |  | 
 | [[SubmitTypePerBranch]] | 
 | === Example 2: `Fast Forward Only` for all `+refs/heads/stable*+` branches | 
 | For all `+refs/heads/stable*+` branches we would like to enforce the `Fast | 
 | Forward Only` submit type. A reason for this decision may be a need to never | 
 | break the build in the stable branches.  For all other branches, those not | 
 | matching the `+refs/heads/stable*+` pattern, we would like to use the project's | 
 | default submit type as defined on the project settings page. | 
 |  | 
 | `rules.pl` | 
 | [source,prolog] | 
 | ---- | 
 | submit_type(fast_forward_only) :- | 
 |     gerrit:change_branch(B), regex_matches('refs/heads/stable.*', B), | 
 |     !. | 
 | submit_type(T) :- gerrit:project_default_submit_type(T). | 
 | ---- | 
 |  | 
 | The first `submit_type` predicate defines the `Fast Forward Only` submit type | 
 | for `+refs/heads/stable.*+` branches. The second `submit_type` predicate returns | 
 | the project's default submit type. | 
 |  | 
 | GERRIT | 
 | ------ | 
 | Part of link:index.html[Gerrit Code Review] | 
 |  | 
 | SEARCHBOX | 
 | --------- |