diff options
author | Luca Milanesio <luca.milanesio@gmail.com> | 2020-06-01 13:40:49 +0100 |
---|---|---|
committer | Luca Milanesio <luca.milanesio@gmail.com> | 2020-06-01 13:54:16 +0100 |
commit | 96f9751ba8ffd518ec381c483afbf558ce9fbb41 (patch) | |
tree | e52348d5536e076462ea8a1410d4121e823d3bb1 | |
parent | f8132e45e76be7358f9ea00b786e014036fc26ae (diff) | |
parent | 92b792a78fed2adeec0dc47686d23a392b9dd612 (diff) |
Merge branch 'stable-3.1' into stable-3.2
* stable-3.1:
When writing temporary plugin files, ensure the directory exists
Update git submodules
Update git submodules
Fix gr-label-info test
Set version to 2.16.21-SNAPSHOT
Set version to 2.16.20
Trim parameterized strings evaluated from LdapRealm
Update account full name when it changes in LDAP
Set Api version for plugin jars
Update git submodules
Update git submodules
Update git submodules
Update git submodules
Update git submodules
Update git submodules
e2e-tests: Add {Approve|Submit}Change core scenarios
Hide "No Votes" notice for for labels added and approved by rules
Change-Id: I5c2450f3ead115d143102eeaff990e8daf66f5e8
20 files changed, 268 insertions, 25 deletions
diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/ApproveChange-body.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/ApproveChange-body.json new file mode 100644 index 0000000000..670aa9f07b --- /dev/null +++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/ApproveChange-body.json @@ -0,0 +1,5 @@ +{ + "labels": { + "Code-Review": 2 + } +} diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/ApproveChange.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/ApproveChange.json new file mode 100644 index 0000000000..3577a6a35b --- /dev/null +++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/ApproveChange.json @@ -0,0 +1,6 @@ +[ + { + "url": "http://HOSTNAME:HTTP_PORT/a/changes/", + "number": "NUMBER" + } +] diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateChange.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateChange.json index c267ab3204..b4ee549d26 100644 --- a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateChange.json +++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/CreateChange.json @@ -1,6 +1,6 @@ [ { "url": "http://HOSTNAME:HTTP_PORT/a/changes/", - "project": "_PROJECT" + "project": "PROJECT" } ] diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteChange.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteChange.json index 53b947a248..3577a6a35b 100644 --- a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteChange.json +++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/DeleteChange.json @@ -1,6 +1,6 @@ [ { "url": "http://HOSTNAME:HTTP_PORT/a/changes/", - "number": "_NUMBER" + "number": "NUMBER" } ] diff --git a/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/SubmitChange.json b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/SubmitChange.json new file mode 100644 index 0000000000..a371757d23 --- /dev/null +++ b/e2e-tests/src/test/resources/data/com/google/gerrit/scenarios/SubmitChange.json @@ -0,0 +1,5 @@ +[ + { + "url": "http://HOSTNAME:HTTP_PORT/a/changes/" + } +] diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/ApproveChange.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/ApproveChange.scala new file mode 100644 index 0000000000..fe46bd6506 --- /dev/null +++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/ApproveChange.scala @@ -0,0 +1,48 @@ +// Copyright (C) 2020 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. + +package com.google.gerrit.scenarios + +import io.gatling.core.Predef.{atOnceUsers, _} +import io.gatling.core.feeder.FeederBuilder +import io.gatling.core.structure.ScenarioBuilder +import io.gatling.http.Predef.http + +class ApproveChange extends GerritSimulation { + private val data: FeederBuilder = jsonFile(resource).convert(keys).queue + private var createChange: Option[CreateChange] = None + + def this(createChange: CreateChange) { + this() + this.createChange = Some(createChange) + } + + val test: ScenarioBuilder = scenario(unique) + .feed(data) + .exec(session => { + if (createChange.nonEmpty) { + session.set("number", createChange.get.number) + } else { + session + } + }) + .exec(http(unique) + .post("${url}${number}/revisions/current/review") + .body(ElFileBody(body)).asJson) + + setUp( + test.inject( + atOnceUsers(1) + )).protocols(httpProtocol) +} diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateChange.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateChange.scala index 57e6bcddc6..c7fb8ed279 100644 --- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateChange.scala +++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/CreateChange.scala @@ -21,26 +21,31 @@ import io.gatling.http.Predef._ import scala.concurrent.duration._ -class CreateChange extends GerritSimulation { +class CreateChange extends ProjectSimulation { private val data: FeederBuilder = jsonFile(resource).convert(keys).queue - private val default: String = name private val numberKey = "_number" + var number = 0 override def relativeRuntimeWeight = 2 - private val test: ScenarioBuilder = scenario(unique) + def this(default: String) { + this() + this.default = default + } + + val test: ScenarioBuilder = scenario(unique) .feed(data) .exec(httpRequest .body(ElFileBody(body)).asJson .check(regex("\"" + numberKey + "\":(\\d+),").saveAs(numberKey))) .exec(session => { - deleteChange.number = Some(session(numberKey).as[Int]) + number = session(numberKey).as[Int] session }) private val createProject = new CreateProject(default) private val deleteProject = new DeleteProject(default) - private val deleteChange = new DeleteChange + private val deleteChange = new DeleteChange(this) setUp( createProject.test.inject( diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteChange.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteChange.scala index 1b3bbc1e98..aa6fe0d0dc 100644 --- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteChange.scala +++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/DeleteChange.scala @@ -21,15 +21,20 @@ import io.gatling.http.Predef.http class DeleteChange extends GerritSimulation { private val data: FeederBuilder = jsonFile(resource).convert(keys).queue - var number: Option[Int] = None + private var createChange: Option[CreateChange] = None override def relativeRuntimeWeight = 2 + def this(createChange: CreateChange) { + this() + this.createChange = Some(createChange) + } + val test: ScenarioBuilder = scenario(unique) .feed(data) .exec(session => { - if (number.nonEmpty) { - session.set("number", number.get) + if (createChange.nonEmpty) { + session.set("number", createChange.get.number) } else { session } diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala index b427c0d036..5d6176d1c7 100644 --- a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala +++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/GerritSimulation.scala @@ -66,7 +66,8 @@ class GerritSimulation extends Simulation { val precedes = replaceKeyWith("_number", 0, number.toString) replaceProperty("number", 1, precedes) case ("project", project) => - val precedes = replaceKeyWith("_project", name, project.toString) + var precedes = replaceKeyWith("_project", name, project.toString) + precedes = replaceOverride(precedes) replaceProperty("project", precedes) case ("entries", entries) => replaceProperty("projects_entries", "1", entries.toString) diff --git a/e2e-tests/src/test/scala/com/google/gerrit/scenarios/SubmitChange.scala b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/SubmitChange.scala new file mode 100644 index 0000000000..2f67274d3f --- /dev/null +++ b/e2e-tests/src/test/scala/com/google/gerrit/scenarios/SubmitChange.scala @@ -0,0 +1,62 @@ +// Copyright (C) 2020 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. + +package com.google.gerrit.scenarios + +import io.gatling.core.Predef.{atOnceUsers, _} +import io.gatling.core.feeder.FeederBuilder +import io.gatling.core.structure.ScenarioBuilder +import io.gatling.http.Predef.http + +import scala.concurrent.duration._ + +class SubmitChange extends GerritSimulation { + private val data: FeederBuilder = jsonFile(resource).convert(keys).queue + private val default: String = name + + private val test: ScenarioBuilder = scenario(unique) + .feed(data) + .exec(session => { + session.set("number", createChange.number) + }) + .exec(http(unique).post("${url}${number}/submit")) + + private val createProject = new CreateProject(default) + private val createChange = new CreateChange(default) + private val approveChange = new ApproveChange(createChange) + private val deleteProject = new DeleteProject(default) + + setUp( + createProject.test.inject( + nothingFor(stepWaitTime(createProject) seconds), + atOnceUsers(1) + ), + createChange.test.inject( + nothingFor(stepWaitTime(createChange) seconds), + atOnceUsers(1) + ), + approveChange.test.inject( + nothingFor(stepWaitTime(approveChange) seconds), + atOnceUsers(1) + ), + test.inject( + nothingFor(stepWaitTime(this) seconds), + atOnceUsers(1) + ), + deleteProject.test.inject( + nothingFor(stepWaitTime(deleteProject) seconds), + atOnceUsers(1) + ), + ).protocols(httpProtocol) +} diff --git a/java/com/google/gerrit/server/account/AccountManager.java b/java/com/google/gerrit/server/account/AccountManager.java index 345da8109f..7a5b1aae5d 100644 --- a/java/com/google/gerrit/server/account/AccountManager.java +++ b/java/com/google/gerrit/server/account/AccountManager.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -78,8 +79,9 @@ public class AccountManager { private final boolean autoUpdateAccountActiveStatus; private final SetInactiveFlag setInactiveFlag; + @VisibleForTesting @Inject - AccountManager( + public AccountManager( Sequences sequences, @GerritServerConfig Config cfg, Accounts accounts, @@ -239,13 +241,7 @@ public class AccountManager { if (!Strings.isNullOrEmpty(who.getDisplayName()) && !Objects.equals(user.getAccount().fullName(), who.getDisplayName())) { - if (realm.allowsEdit(AccountFieldName.FULL_NAME)) { - accountUpdates.add(a -> a.setFullName(who.getDisplayName())); - } else { - logger.atWarning().log( - "Not changing already set display name '%s' to '%s'", - user.getAccount().fullName(), who.getDisplayName()); - } + accountUpdates.add(a -> a.setFullName(who.getDisplayName())); } if (!realm.allowsEdit(AccountFieldName.USER_NAME) diff --git a/java/com/google/gerrit/server/auth/ldap/LdapRealm.java b/java/com/google/gerrit/server/auth/ldap/LdapRealm.java index c53ba8386b..1421f1792e 100644 --- a/java/com/google/gerrit/server/auth/ldap/LdapRealm.java +++ b/java/com/google/gerrit/server/auth/ldap/LdapRealm.java @@ -218,7 +218,7 @@ class LdapRealm extends AbstractRealm { values.put(name, m.get(name)); } - String r = p.replace(values); + String r = p.replace(values).trim(); return r.isEmpty() ? null : r; } diff --git a/java/com/google/gerrit/server/plugins/JarPluginProvider.java b/java/com/google/gerrit/server/plugins/JarPluginProvider.java index 5b800596ee..82f97c95e6 100644 --- a/java/com/google/gerrit/server/plugins/JarPluginProvider.java +++ b/java/com/google/gerrit/server/plugins/JarPluginProvider.java @@ -110,9 +110,6 @@ public class JarPluginProvider implements ServerPluginProvider { public static Path storeInTemp(String pluginName, InputStream in, SitePaths sitePaths) throws IOException { - if (!Files.exists(sitePaths.tmp_dir)) { - Files.createDirectories(sitePaths.tmp_dir); - } return PluginUtil.asTemp(in, tempNameFor(pluginName), ".jar", sitePaths.tmp_dir); } diff --git a/java/com/google/gerrit/server/plugins/PluginUtil.java b/java/com/google/gerrit/server/plugins/PluginUtil.java index d4110ca8d2..932a01d143 100644 --- a/java/com/google/gerrit/server/plugins/PluginUtil.java +++ b/java/com/google/gerrit/server/plugins/PluginUtil.java @@ -53,6 +53,7 @@ public class PluginUtil { } static Path asTemp(InputStream in, String prefix, String suffix, Path dir) throws IOException { + Files.createDirectories(dir); Path tmp = Files.createTempFile(dir, prefix, suffix); boolean keep = false; try (OutputStream out = Files.newOutputStream(tmp)) { diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java index a09284e982..b41a2f3290 100644 --- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java +++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java @@ -26,6 +26,8 @@ import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.config.GerritConfig; import com.google.gerrit.common.Nullable; import com.google.gerrit.entities.Account; +import com.google.gerrit.extensions.client.AccountFieldName; +import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.ServerInitiated; import com.google.gerrit.server.account.AccountException; import com.google.gerrit.server.account.AccountManager; @@ -33,12 +35,16 @@ import com.google.gerrit.server.account.AccountState; import com.google.gerrit.server.account.AccountsUpdate; import com.google.gerrit.server.account.AuthRequest; import com.google.gerrit.server.account.AuthResult; +import com.google.gerrit.server.account.SetInactiveFlag; import com.google.gerrit.server.account.externalids.ExternalId; import com.google.gerrit.server.account.externalids.ExternalIdNotes; import com.google.gerrit.server.account.externalids.ExternalIds; import com.google.gerrit.server.git.meta.MetaDataUpdate; +import com.google.gerrit.server.group.db.GroupsUpdate; import com.google.gerrit.server.notedb.Sequences; +import com.google.gerrit.server.ssh.SshKeyCache; import com.google.inject.Inject; +import com.google.inject.util.Providers; import java.util.Optional; import java.util.Set; import org.eclipse.jgit.lib.Repository; @@ -51,6 +57,12 @@ public class AccountManagerIT extends AbstractDaemonTest { @Inject @ServerInitiated private AccountsUpdate accountsUpdate; @Inject private ExternalIdNotes.Factory extIdNotesFactory; + @Inject private Sequences sequences; + @Inject private IdentifiedUser.GenericFactory userFactory; + @Inject private SshKeyCache sshKeyCache; + @Inject private GroupsUpdate.Factory groupsUpdateFactory; + @Inject private SetInactiveFlag setInactiveFlag; + @Test public void authenticateNewAccountWithEmail() throws Exception { String email = "foo@example.com"; @@ -200,6 +212,31 @@ public class AccountManagerIT extends AbstractDaemonTest { @Test public void authenticateWithUsernameAndUpdateDisplayName() throws Exception { + authenticateWithUsernameAndUpdateDisplayName(accountManager); + } + + @Test + public void readOnlyFullNameField_authenticateWithUsernameAndUpdateDisplayName() + throws Exception { + TestRealm realm = server.getTestInjector().getInstance(TestRealm.class); + realm.denyEdit(AccountFieldName.FULL_NAME); + authenticateWithUsernameAndUpdateDisplayName( + new AccountManager( + sequences, + cfg, + accounts, + Providers.of(accountsUpdate), + accountCache, + realm, + userFactory, + sshKeyCache, + projectCache, + externalIds, + groupsUpdateFactory, + setInactiveFlag)); + } + + private void authenticateWithUsernameAndUpdateDisplayName(AccountManager am) throws Exception { String username = "foo"; String email = "foo@example.com"; Account.Id accountId = Account.id(seq.nextAccountId()); @@ -215,7 +252,7 @@ public class AccountManagerIT extends AbstractDaemonTest { AuthRequest who = AuthRequest.forUser(username); String newName = "Updated Name"; who.setDisplayName(newName); - AuthResult authResult = accountManager.authenticate(who); + AuthResult authResult = am.authenticate(who); assertAuthResultForExistingAccount(authResult, accountId, gerritExtIdKey); Optional<AccountState> accountState = accounts.get(accountId); diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/BUILD b/javatests/com/google/gerrit/acceptance/api/accounts/BUILD index 2167d27efd..673379dda0 100644 --- a/javatests/com/google/gerrit/acceptance/api/accounts/BUILD +++ b/javatests/com/google/gerrit/acceptance/api/accounts/BUILD @@ -1,3 +1,4 @@ +load("@rules_java//java:defs.bzl", "java_library") load("//javatests/com/google/gerrit/acceptance:tests.bzl", "acceptance_tests") acceptance_tests( @@ -9,8 +10,18 @@ acceptance_tests( "no_windows", ], deps = [ + ":util", "//java/com/google/gerrit/git", "//java/com/google/gerrit/mail", "//java/com/google/gerrit/server/util/time", ], ) + +java_library( + name = "util", + testonly = True, + srcs = glob(["TestRealm.java"]), + deps = [ + "//java/com/google/gerrit/acceptance:lib", + ], +) diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/TestRealm.java b/javatests/com/google/gerrit/acceptance/api/accounts/TestRealm.java new file mode 100644 index 0000000000..94b6cd38ba --- /dev/null +++ b/javatests/com/google/gerrit/acceptance/api/accounts/TestRealm.java @@ -0,0 +1,46 @@ +// Copyright (C) 2020 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. + +package com.google.gerrit.acceptance.api.accounts; + +import com.google.gerrit.extensions.client.AccountFieldName; +import com.google.gerrit.server.account.DefaultRealm; +import com.google.gerrit.server.account.EmailExpander; +import com.google.gerrit.server.account.Emails; +import com.google.gerrit.server.config.AuthConfig; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import java.util.HashSet; +import java.util.Set; + +@Singleton +public class TestRealm extends DefaultRealm { + + private final Set<AccountFieldName> readOnlyFields = new HashSet<>(); + + @Inject + public TestRealm(EmailExpander emailExpander, Provider<Emails> emails, AuthConfig authConfig) { + super(emailExpander, emails, authConfig); + } + + public void denyEdit(AccountFieldName field) { + readOnlyFields.add(field); + } + + @Override + public boolean allowsEdit(AccountFieldName field) { + return !readOnlyFields.contains(field); + } +} diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js index 2c5589f4f6..22bdce16d2 100644 --- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js +++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js @@ -170,6 +170,11 @@ class GrLabelInfo extends GestureEventListeners( * order to trigger computation when a label is removed from the change. */ _computeShowPlaceholder(labelInfo, changeLabelsRecord) { + if (labelInfo && + !labelInfo.values && (labelInfo.rejected || labelInfo.approved)) { + return 'hidden'; + } + if (labelInfo && labelInfo.all) { for (const label of labelInfo.all) { if (label.value && label.value != labelInfo.default_value) { diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html index a340550421..d7ccc45d19 100644 --- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html +++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html @@ -232,6 +232,18 @@ suite('gr-account-link tests', () => { element.labelInfo = {all: [{value: 1}]}; assert.isTrue(isHidden(element.shadowRoot .querySelector('.placeholder'))); + element.labelInfo = {rejected: []}; + assert.isTrue(isHidden(element.shadowRoot + .querySelector('.placeholder'))); + element.labelInfo = {values: [], rejected: [], all: [{value: 1}]}; + assert.isTrue(isHidden(element.shadowRoot + .querySelector('.placeholder'))); + element.labelInfo = {approved: []}; + assert.isTrue(isHidden(element.shadowRoot + .querySelector('.placeholder'))); + element.labelInfo = {values: [], approved: [], all: [{value: 1}]}; + assert.isTrue(isHidden(element.shadowRoot + .querySelector('.placeholder'))); }); }); </script> diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl index 3cffb79a81..61b12f122b 100644 --- a/tools/bzl/plugin.bzl +++ b/tools/bzl/plugin.bzl @@ -1,5 +1,6 @@ load("@rules_java//java:defs.bzl", "java_binary", "java_library") load("//tools/bzl:genrule2.bzl", "genrule2") +load("//:version.bzl", "GERRIT_VERSION") PLUGIN_DEPS = ["//plugins:plugin-lib"] @@ -63,7 +64,7 @@ def gerrit_plugin( "GEN_VERSION=$$(cat bazel-out/stable-status.txt | grep -w STABLE_BUILD_%s_LABEL | cut -d ' ' -f 2)" % dir_name.upper(), "cd $$TMP", "unzip -q $$ROOT/$<", - "echo \"Implementation-Version: $$GEN_VERSION\n$$(cat META-INF/MANIFEST.MF)\" > META-INF/MANIFEST.MF", + "echo \"Implementation-Version: $$GEN_VERSION\nGerrit-ApiVersion: " + GERRIT_VERSION + "\n$$(cat META-INF/MANIFEST.MF)\" > META-INF/MANIFEST.MF", "find . -exec touch '{}' ';'", "zip -Xqr $$ROOT/$@ .", ]), |