Merge branch 'stable-2.11'
* stable-2.11:
Add sample NewProjectCreatedListener
Build with API version 2.11 and consume from Maven Central
Change-Id: I72593dcfc2f79469499d0c631fe29d07e66536c8
diff --git a/BUCK b/BUCK
index b28f661..081ad6f 100644
--- a/BUCK
+++ b/BUCK
@@ -20,6 +20,8 @@
java_test(
name = 'cookbook_tests',
srcs = glob(['src/test/java/**/*.java']),
+ labels = ['cookbook-plugin'],
+ source_under_test = [':cookbook-plugin__plugin'],
deps = [
':cookbook-plugin__plugin',
'//lib:junit',
diff --git a/lib/gerrit/BUCK b/lib/gerrit/BUCK
index 3d891ea..ee02ebb 100644
--- a/lib/gerrit/BUCK
+++ b/lib/gerrit/BUCK
@@ -1,7 +1,7 @@
include_defs('//bucklets/maven_jar.bucklet')
-VER = '2.11'
-REPO = MAVEN_CENTRAL
+VER = '2.12-SNAPSHOT'
+REPO = MAVEN_LOCAL
maven_jar(
name = 'plugin-api',
diff --git a/pom.xml b/pom.xml
index 5280bc9..b7ff1cc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
<groupId>com.googlesource.gerrit.plugins</groupId>
<artifactId>cookbook-plugin</artifactId>
<packaging>jar</packaging>
- <version>2.11</version>
+ <version>2.12-SNAPSHOT</version>
<properties>
<Gerrit-ApiType>plugin</Gerrit-ApiType>
<Gerrit-ApiVersion>${project.version}</Gerrit-ApiVersion>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/CommitValidator.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/CommitValidator.java
new file mode 100644
index 0000000..9bc6f5d
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/CommitValidator.java
@@ -0,0 +1,38 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.server.events.CommitReceivedEvent;
+import com.google.gerrit.server.git.validators.CommitValidationException;
+import com.google.gerrit.server.git.validators.CommitValidationListener;
+import com.google.gerrit.server.git.validators.CommitValidationMessage;
+
+import java.util.List;
+
+public class CommitValidator implements CommitValidationListener {
+ @Override
+ public List<CommitValidationMessage> onCommitReceived(
+ CommitReceivedEvent receiveEvent) throws CommitValidationException {
+ if ("plugins/cookbook".equals(receiveEvent.project.getName()) &&
+ !receiveEvent.commit.getShortMessage().startsWith("Cookbook: ")) {
+ CommitValidationMessage m = new CommitValidationMessage(
+ "Subject should begin with 'Cookbook: '", true);
+ throw new CommitValidationException(
+ "Invalid commit message", ImmutableList.of(m));
+ }
+ return ImmutableList.of();
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
index 58a9017..f53b066 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
@@ -17,17 +17,12 @@
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.change.RevisionResource;
-import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
class Greetings implements RestReadView<RevisionResource> {
- @Inject
- Greetings() {
- }
-
@Override
public Response<Collection<GreetInfo>> apply(RevisionResource rev) {
Collection<GreetInfo> l = new ArrayList<>(3);
@@ -40,7 +35,7 @@
return Response.ok(l);
}
- class GreetInfo {
+ static class GreetInfo {
String message;
String country;
String href;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java
index 2d09990..e2689b9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java
@@ -29,6 +29,7 @@
import com.google.gerrit.extensions.webui.ProjectWebLink;
import com.google.gerrit.extensions.webui.TopMenu;
import com.google.gerrit.server.config.ProjectConfigEntry;
+import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.MergeValidationListener;
import com.google.gerrit.server.git.validators.UploadValidationListener;
import com.google.gerrit.server.plugins.ServerPluginProvider;
@@ -64,6 +65,8 @@
.to(MergeUserValidator.class);
DynamicSet.bind(binder(), HashtagValidationListener.class)
.to(HashtagValidator.class);
+ DynamicSet.bind(binder(), CommitValidationListener.class)
+ .to(CommitValidator.class);
DynamicSet.bind(binder(), NewProjectCreatedListener.class)
.to(ProjectCreatedListener.class);
configurePluginParameters();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/BuildsDropDownPanel.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/BuildsDropDownPanel.java
new file mode 100644
index 0000000..86b7034
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/BuildsDropDownPanel.java
@@ -0,0 +1,74 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gerrit.plugin.client.extension.Panel;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.InlineHyperlink;
+import com.google.gwt.user.client.ui.InlineLabel;
+
+/**
+ * Extension for change screen that displays a status in the header bar.
+ */
+public class BuildsDropDownPanel extends FlowPanel {
+ static class Factory implements Panel.EntryPoint {
+ @Override
+ public void onLoad(Panel panel) {
+ panel.setWidget(new BuildsDropDownPanel());
+ }
+ }
+
+ BuildsDropDownPanel() {
+ Grid g = new Grid(3, 4);
+ g.addStyleName("infoBlock");
+ CellFormatter fmt = g.getCellFormatter();
+
+ g.setText(0, 0, "State");
+ fmt.addStyleName(0, 0, "header");
+ g.setText(0, 1, "PS");
+ fmt.addStyleName(0, 1, "header");
+ g.setText(0, 2, "Date");
+ fmt.addStyleName(0, 2, "header");
+ g.setText(0, 3, "Log");
+ fmt.addStyleName(0, 3, "header");
+
+ HorizontalPanel p = new HorizontalPanel();
+ p.add(new Image(CookBookPlugin.RESOURCES.greenCheck()));
+ p.add(new InlineLabel("OK"));
+ g.setWidget(1, 0, p);
+ g.setWidget(1, 1, new InlineLabel("2"));
+ g.setWidget(1, 2, new InlineLabel("2015-07-09 11:06:13"));
+ g.setWidget(1, 3, new InlineHyperlink("Build Log", "TODO"));
+
+ p = new HorizontalPanel();
+ p.add(new Image(CookBookPlugin.RESOURCES.redNot()));
+ p.add(new InlineLabel("FAILED"));
+ g.setWidget(2, 0, p);
+ g.setWidget(2, 1, new InlineLabel("1"));
+ g.setWidget(2, 2, new InlineLabel("2015-07-09 09:17:28"));
+ g.setWidget(2, 3, new InlineHyperlink("Build Log", "TODO"));
+
+ fmt.addStyleName(0, 0, "topmost");
+ fmt.addStyleName(0, 1, "topmost");
+ fmt.addStyleName(0, 2, "topmost");
+ fmt.addStyleName(0, 3, "topmost");
+
+ add(new PopDownButton("Builds", g));
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/ChangeScreenStatusExtension.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/ChangeScreenStatusExtension.java
new file mode 100644
index 0000000..e0ceeed
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/ChangeScreenStatusExtension.java
@@ -0,0 +1,39 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gerrit.plugin.client.extension.Panel;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.InlineLabel;
+
+/**
+ * Extension for change screen that displays a status in the header bar.
+ */
+public class ChangeScreenStatusExtension extends FlowPanel {
+ static class Factory implements Panel.EntryPoint {
+ @Override
+ public void onLoad(Panel panel) {
+ panel.setWidget(new ChangeScreenStatusExtension());
+ }
+ }
+
+ ChangeScreenStatusExtension() {
+ getElement().getStyle().setPadding(5, Unit.PX);
+ add(new Image(CookBookPlugin.RESOURCES.greenCheck()));
+ add(new InlineLabel("OK"));
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookChangeScreenExtension.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookChangeScreenExtension.java
new file mode 100644
index 0000000..faf4c0e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookChangeScreenExtension.java
@@ -0,0 +1,54 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gerrit.client.GerritUiExtensionPoint;
+import com.google.gerrit.client.info.ChangeInfo;
+import com.google.gerrit.plugin.client.extension.Panel;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwtexpui.clippy.client.CopyableLabel;
+
+/**
+ * Extension for change screen that displays the numeric change ID with
+ * copy-to-clipboard icon.
+ */
+public class CookBookChangeScreenExtension extends VerticalPanel {
+ static class Factory implements Panel.EntryPoint {
+ @Override
+ public void onLoad(Panel panel) {
+ panel.setWidget(new CookBookChangeScreenExtension(panel));
+ }
+ }
+
+ CookBookChangeScreenExtension(Panel panel) {
+ ChangeInfo change =
+ panel.getObject(GerritUiExtensionPoint.Key.CHANGE_INFO).cast();
+
+ Grid g = new Grid(1, 2);
+ g.addStyleName("infoBlock");
+ CellFormatter fmt = g.getCellFormatter();
+
+ g.setText(0, 0, "Numeric Change ID");
+ fmt.addStyleName(0, 0, "header");
+ g.setWidget(0, 1, new CopyableLabel(Integer.toString(change._number())));
+ add(g);
+
+ fmt.addStyleName(0, 0, "topmost");
+ fmt.addStyleName(0, 1, "topmost");
+ fmt.addStyleName(0, 0, "bottomheader");
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookPlugin.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookPlugin.java
index e9ace38..7a56ca0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookPlugin.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookPlugin.java
@@ -14,12 +14,49 @@
package com.googlesource.gerrit.plugins.cookbook.client;
+import com.google.gerrit.client.GerritUiExtensionPoint;
+import com.google.gerrit.client.Resources;
import com.google.gerrit.plugin.client.Plugin;
import com.google.gerrit.plugin.client.PluginEntryPoint;
+import com.google.gerrit.plugin.client.extension.Panel;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
public class CookBookPlugin extends PluginEntryPoint {
+ public static final Resources RESOURCES = GWT.create(Resources.class);
+
@Override
public void onPluginLoad() {
Plugin.get().screen("", new IndexScreen.Factory());
+ Plugin.get().settingsScreen("preferences", "Food Preferences",
+ new FoodPreferencesScreen.Factory());
+ Plugin.get().panel(GerritUiExtensionPoint.PROFILE_SCREEN_BOTTOM,
+ new CookBookProfileExtension.Factory());
+ Plugin.get().panel(
+ GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK,
+ new CookBookChangeScreenExtension.Factory());
+ Plugin.get().panel(GerritUiExtensionPoint.CHANGE_SCREEN_HEADER,
+ new ChangeScreenStatusExtension.Factory());
+ Plugin.get().panel(
+ GerritUiExtensionPoint.CHANGE_SCREEN_HEADER_RIGHT_OF_POP_DOWNS,
+ new BuildsDropDownPanel.Factory());
+ Plugin.get().panel(
+ GerritUiExtensionPoint.CHANGE_SCREEN_HEADER_RIGHT_OF_BUTTONS,
+ new Panel.EntryPoint() {
+ @Override
+ public void onLoad(Panel panel) {
+ Button b = new HighlightButton("Library-Compliance+1");
+ b.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ Window.alert("TODO");
+ }
+ });
+ panel.setWidget(b);
+ }
+ });
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookProfileExtension.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookProfileExtension.java
new file mode 100644
index 0000000..e50427a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/CookBookProfileExtension.java
@@ -0,0 +1,65 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gerrit.client.GerritUiExtensionPoint;
+import com.google.gerrit.client.info.AccountInfo;
+import com.google.gerrit.plugin.client.extension.Panel;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+/**
+ * Extension for the user profile screen.
+ */
+public class CookBookProfileExtension extends VerticalPanel {
+ static class Factory implements Panel.EntryPoint {
+ @Override
+ public void onLoad(Panel panel) {
+ AccountInfo accountInfo =
+ panel.getObject(GerritUiExtensionPoint.Key.ACCOUNT_INFO).cast();
+ panel.setWidget(new CookBookProfileExtension(accountInfo));
+ }
+ }
+
+ CookBookProfileExtension(AccountInfo accountInfo) {
+ Grid g = new Grid(3, 2);
+ g.addStyleName("infoBlock");
+ g.addStyleName("accountInfoBlock");
+ CellFormatter fmt = g.getCellFormatter();
+
+ // TODO: fetch employer and department via REST from server,
+ // e.g. GET /accounts/self/cookbook~info
+
+ g.setText(0, 0, "Employer");
+ fmt.addStyleName(0, 0, "header");
+ g.setText(0, 1, "CookBook Corporation");
+
+ g.setText(1, 0, "Department");
+ fmt.addStyleName(1, 0, "header");
+ g.setText(1, 1, "Cookies " + accountInfo.email());
+
+ g.setText(2, 0, "CookBook Email");
+ fmt.addStyleName(2, 0, "header");
+ g.setText(2, 1, accountInfo.username() != null
+ ? accountInfo.username() + "@cookbook.com"
+ : "N/A");
+ add(g);
+
+ fmt.addStyleName(0, 0, "topmost");
+ fmt.addStyleName(0, 1, "topmost");
+ fmt.addStyleName(2, 0, "bottomheader");
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/FoodPreferencesScreen.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/FoodPreferencesScreen.java
new file mode 100644
index 0000000..6ba46fd
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/FoodPreferencesScreen.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gerrit.plugin.client.screen.Screen;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.TextArea;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+class FoodPreferencesScreen extends VerticalPanel {
+ static class Factory implements Screen.EntryPoint {
+ @Override
+ public void onLoad(Screen screen) {
+ screen.setPageTitle("Settings");
+ screen.show(new FoodPreferencesScreen());
+ }
+ }
+
+ FoodPreferencesScreen() {
+ setStyleName("cookbook-panel");
+
+ Panel messagePanel = new VerticalPanel();
+ messagePanel.add(new Label("Food Allergies or Dietary Concerns:"));
+ TextArea txt = new TextArea();
+ txt.addKeyPressHandler(new KeyPressHandler() {
+ @Override
+ public void onKeyPress(final KeyPressEvent event) {
+ event.stopPropagation();
+ }
+ });
+ txt.setVisibleLines(12);
+ txt.setCharacterWidth(80);
+ txt.getElement().setPropertyBoolean("spellcheck", false);
+ messagePanel.add(txt);
+ add(messagePanel);
+
+ Button helloButton = new Button("Save");
+ helloButton.addStyleName("cookbook-helloButton");
+ helloButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(final ClickEvent event) {
+ Window.alert("TODO: implement save");
+ }
+ });
+ add(helloButton);
+ helloButton.setEnabled(true);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/HighlightButton.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/HighlightButton.java
new file mode 100644
index 0000000..0af633f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/HighlightButton.java
@@ -0,0 +1,36 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
+
+/**
+ * Highlight button for header line in change screen.
+ *
+ * This class can *only* be used within a panel that extends the header line of
+ * the change screen, but will not work standalone.
+ */
+public class HighlightButton extends Button {
+
+ public HighlightButton(String text) {
+ // Create Button with inner div. This is required to get proper styling
+ // in the context of the change screen.
+ super((new SafeHtmlBuilder()).openDiv()
+ .appendAttribute("style", "color: #fff;").append(text).closeDiv());
+ getElement().removeClassName("gwt-Button");
+ getElement().getStyle().setBackgroundColor("#4d90fe");
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java
index 0edf949..774ec3d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java
@@ -14,9 +14,7 @@
package com.googlesource.gerrit.plugins.cookbook.client;
-import com.google.gerrit.client.Resources;
import com.google.gerrit.plugin.client.screen.Screen;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.ClickEvent;
@@ -45,14 +43,13 @@
private TextBox usernameTxt;
private TextArea greetingTxt;
- private Resources RESOURCES = GWT.create(Resources.class);
IndexScreen() {
setStyleName("cookbook-panel");
Panel labelImagePanel = new HorizontalPanel();
Panel usernamePanel = new VerticalPanel();
- Image img = new Image(RESOURCES.info());
+ Image img = new Image(CookBookPlugin.RESOURCES.info());
img.setTitle("User to send greetings to");
labelImagePanel.add(new Label("Username"));
labelImagePanel.add(img);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/PopDownButton.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/PopDownButton.java
new file mode 100644
index 0000000..3cbe5d6
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/PopDownButton.java
@@ -0,0 +1,101 @@
+// Copyright (C) 2015 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.googlesource.gerrit.plugins.cookbook.client;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.FontWeight;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwtexpui.globalkey.client.GlobalKey;
+import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
+
+/**
+ * Pop down button for header line in change screen.
+ *
+ * This class implements a button that on click opens a pop down panel with the
+ * provided widget, similar to the "Patch Sets", "Download" or "Included In" pop
+ * down panels on the change screen.
+ *
+ * This class can *only* be used within a panel that extends the header line of
+ * the change screen, but will not work standalone.
+ */
+public class PopDownButton extends Button {
+ private final Widget widget;
+ private PopupPanel popup;
+
+ public PopDownButton(String text, Widget widget) {
+ // Create Button with inner div. This is required to get proper styling
+ // in the context of the change screen.
+ super((new SafeHtmlBuilder()).openDiv().append(text).closeDiv());
+ getElement().removeClassName("gwt-Button");
+ addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ show();
+ }
+ });
+ this.widget = widget;
+ }
+
+ private void show() {
+ if (popup != null) {
+ getElement().getStyle().clearFontWeight();
+ popup.hide();
+ return;
+ }
+
+ final Widget relativeTo = getParent();
+ final PopupPanel p = new PopupPanel(true) {
+ @Override
+ public void setPopupPosition(int left, int top) {
+ top -= Document.get().getBodyOffsetTop();
+
+ int w = Window.getScrollLeft() + Window.getClientWidth();
+ int r = relativeTo.getAbsoluteLeft() + relativeTo.getOffsetWidth();
+ int right = w - r;
+ Style style = getElement().getStyle();
+ style.clearProperty("left");
+ style.setPropertyPx("right", right);
+ style.setPropertyPx("top", top);
+ }
+ };
+ Style popupStyle = p.getElement().getStyle();
+ popupStyle.setBorderWidth(0, Unit.PX);
+ popupStyle.setBackgroundColor("#EEEEEE");
+ p.addAutoHidePartner(getElement());
+ p.addCloseHandler(new CloseHandler<PopupPanel>() {
+ @Override
+ public void onClose(CloseEvent<PopupPanel> event) {
+ if (popup == p) {
+ getElement().getStyle().clearFontWeight();
+ popup = null;
+ }
+ }
+ });
+ p.add(widget);
+ p.showRelativeTo(relativeTo);
+ GlobalKey.dialog(p);
+ getElement().getStyle().setFontWeight(FontWeight.BOLD);
+ popup = p;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java
index b1da6de..853d04d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java
@@ -14,39 +14,64 @@
package com.googlesource.gerrit.plugins.cookbook.pluginprovider;
+import com.google.gerrit.extensions.annotations.PluginData;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
+import org.kohsuke.args4j.Argument;
-/**
- * SSH command defined by dynamically registered plugins.
- *
- */
-@CommandMetaData(name = "print", description = "Print content of the plugin file")
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+/** SSH command defined by dynamically registered plugins. */
+@CommandMetaData(name = "cat", description = "Print content of plugin file")
public final class HelloSshCommand extends SshCommand {
private final String pluginName;
- private final File pluginDir;
+ private final Path pluginDir;
+ private final Path dataDir;
+
+ @Argument(usage = "files in data directory to print")
+ private List<String> files = new ArrayList<>();
@Inject
- public HelloSshCommand(@PluginName String pluginName, SitePaths sitePaths) {
+ public HelloSshCommand(@PluginName String pluginName,
+ SitePaths sitePaths,
+ @PluginData Path dataDir) {
this.pluginName = pluginName;
- this.pluginDir = sitePaths.plugins_dir;
+ this.pluginDir = sitePaths.plugins_dir.normalize();
+ this.dataDir = dataDir.normalize();
}
@Override
public void run() {
- File pluginFile = new File(pluginDir, pluginName + ".ssh");
+ Path pluginPath = pluginDir.resolve(pluginName + ".ssh");
+ printOne(pluginPath);
+ for (String name : files) {
+ Path p = dataDir.resolve(name).normalize();
+ if (!p.startsWith(dataDir)) {
+ throw new RuntimeException(p + " is outside data directory " + dataDir);
+ }
+ printOne(p);
+ }
+ }
+
+ private void printOne(Path p) {
try {
- Files.copy(pluginFile.toPath(), out);
+ Files.copy(p, out);
} catch (IOException e) {
- throw new RuntimeException("Cannot read plugin content of " + pluginFile,
- e);
+ try (PrintWriter w = new PrintWriter(err)) {
+ w.write("Error reading contents of ");
+ w.write(p.toAbsolutePath().toString());
+ w.write(": \n");
+ e.printStackTrace(w);
+ }
}
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java
index a7d7268..8ffd8c2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java
@@ -22,19 +22,25 @@
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
-import java.io.File;
+import java.nio.file.Path;
/**
- * Dynamic provider of Gerrit plugins derived by *.ssh files under $GERRIT_SITE/plugins.
- *
+ * Dynamic provider of Gerrit plugins derived by *.ssh files under
+ * $GERRIT_SITE/plugins.
+ * <p>
* Example of how to define a dynamic Gerrit plugin provider to register
* a new plugin based on the content of *.ssh files.
- *
+ * <p>
* This provider allows to define a Gerrit plugin by simply dropping a .ssh file
* (e.g. hello.ssh) under $GERRIT_SITE/plugins.
+ * <p>
* Once the file is created a new plugin is automatically loaded with the name
- * without extension of the .ssh file (e.g. hello) and a new 'cat' SSH command is
- * automatically available from the registered plugin.
+ * without extension of the .ssh file (e.g. hello) and a new 'cat' SSH command
+ * is automatically available from the registered plugin.
+ * <p>
+ * The 'cat' command will print the contents of the .ssh file, along with the
+ * contents of any arguments, resolved against the plugin's data directory
+ * $GERRIT_SITE/data/name.
*/
public class HelloSshPluginProvider implements ServerPluginProvider {
private static final String SSH_EXT = ".ssh";
@@ -46,22 +52,22 @@
}
@Override
- public boolean handles(File srcFile) {
- return srcFile.getName().endsWith(SSH_EXT);
+ public boolean handles(Path srcPath) {
+ return srcPath.getFileName().toString().endsWith(SSH_EXT);
}
@Override
- public String getPluginName(File srcFile) {
- String srcFileName = srcFile.getName();
- return srcFileName.substring(0, srcFileName.length() - SSH_EXT.length());
+ public String getPluginName(Path srcPath) {
+ String name = srcPath.getFileName().toString();
+ return name.substring(0, name.length() - SSH_EXT.length());
}
@Override
- public ServerPlugin get(File srcFile, FileSnapshot snapshot,
+ public ServerPlugin get(Path srcPath, FileSnapshot snapshot,
PluginDescription pluginDescriptor) throws InvalidPluginException {
- String name = getPluginName(srcFile);
+ String name = getPluginName(srcPath);
return new ServerPlugin(name, pluginDescriptor.canonicalUrl,
- pluginDescriptor.user, srcFile, snapshot,
+ pluginDescriptor.user, srcPath, snapshot,
new HelloSshPluginContentScanner(name), pluginDescriptor.dataDir,
getClass().getClassLoader());
}