Merge "Use ApprovalsUtil.addReviewers() for PostReviewers"
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index b6f7d7c..facc8f2 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -542,13 +542,12 @@
configuration. Users who are members of an owner group can:
* Change the project description
-* Create/delete a branch through the web UI (not SSH)
+* Create a branch through SSH
+* Create/delete a branch through the web UI
* Grant/revoke any access rights, including `Owner`
-Note that project owners implicitly have branch creation or deletion
-through the web UI, but not through SSH. To get SSH branch access
-project owners must grant an access right to a group they are a
-member of, just like for any other user.
+To get SSH branch access project owners must grant an access right to a group
+they are a member of, just like for any other user.
Ownership over a particular branch subspace may be delegated by
entering a branch pattern. To delegate control over all branches
diff --git a/Documentation/cmd-create-branch.txt b/Documentation/cmd-create-branch.txt
new file mode 100644
index 0000000..6e6d561
--- /dev/null
+++ b/Documentation/cmd-create-branch.txt
@@ -0,0 +1,58 @@
+gerrit create-branch
+====================
+
+NAME
+----
+gerrit create-branch - Create a new branch
+
+SYNOPSIS
+--------
+--
+'ssh' -p <port> <host> 'gerrit create-branch'
+ <PROJECT>
+ <NAME>
+ <REVISION>
+--
+
+DESCRIPTION
+-----------
+Creates a new branch for a project.
+
+ACCESS
+------
+Caller should have link:access-control.html#category_create[Create Reference]
+permission on the project.
+
+Administrators do not automatically have permission to create branches. It must
+be granted via the Create Reference permission.
+
+SCRIPTING
+---------
+This command is intended to be used in scripts.
+
+OPTIONS
+-------
+<PROJECT>::
+ Required; name of the project.
+
+<NAME>::
+ Required; name of the branch to be created.
+
+<REVISION>::
+ Required; base revision of the new branch.
+
+EXAMPLES
+--------
+Create a new branch called 'newbranch' from the 'master' branch of
+the project 'myproject'.
+
+====
+ $ ssh -p 29418 review.example.com gerrit create-branch myproject newbranch master
+====
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt
index 4e62451..6ddfa36 100644
--- a/Documentation/cmd-index.txt
+++ b/Documentation/cmd-index.txt
@@ -96,6 +96,9 @@
Also implements the magic associated with uploading commits for
review. See link:user-upload.html#push_create[Creating Changes].
+link:cmd-create-branch.html[gerrit create-branch]::
+ Create a new project branch.
+
[[admin_commands]]Administrator Commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/dev-buck.txt b/Documentation/dev-buck.txt
index 611d64d..7b4981a 100644
--- a/Documentation/dev-buck.txt
+++ b/Documentation/dev-buck.txt
@@ -7,7 +7,7 @@
There is currently no binary distribution of Buck, so it has to be manually
built and installed. Apache Ant is required. Currently only Linux and Mac
-OS are supported.
+OS are supported. Gerrit's buck wrappers require Python version 2.6 or higher.
Clone the git and build it:
@@ -130,7 +130,7 @@
----
Java binaries, Java sources and Java docs are generated into corresponding
-project directories in buck-out/gen, here as example for plugin API:
+project directories in `buck-out/gen`, here as example for plugin API:
----
buck-out/gen/gerrit-plugin-api/plugin-api.jar
@@ -144,7 +144,7 @@
buck build api_install
----
-Deploy {extension,plugin,gwt}-api to the remote maven repository
+Deploy {extension,plugin,gwt}-api to the remote maven repository:
----
buck build api_deploy
@@ -154,6 +154,11 @@
* 2.9-SNAPSHOT: snapshot repo
* 2.9: release repo
+Deploying to the remote repository still depends on Maven, and the credentials
+for the repository need to be
+link:dev-release-deploy-config.html#deploy-configuration-settings-xml[
+configured in Maven's settings.xml file].
+
Plugins
~~~~~~~
diff --git a/Documentation/dev-readme.txt b/Documentation/dev-readme.txt
index e73e039..10455c0 100644
--- a/Documentation/dev-readme.txt
+++ b/Documentation/dev-readme.txt
@@ -28,6 +28,23 @@
link:dev-buck.html#build[Building on the command line with Buck].
+Switching between branches
+--------------------------
+
+When switching between branches with `git checkout`, be aware that
+submodule revisions are not altered. This may result in the wrong
+plugin revisions being present, unneeded plugins being present, or
+expected plugins being missing.
+
+After switching branches, make sure the submodules are at the correct
+revisions for the new branch with the commands:
+
+----
+ git submodule update
+ git clean -fdx
+----
+
+
Configuring Eclipse
-------------------
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
index 5bb207d..0020647 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
@@ -199,8 +199,10 @@
String projectFilterPanel();
String projectNameColumn();
String publishCommentsScreen();
- String relatedChangesTabPanel();
+ String relatedChangesGitweb();
+ String relatedChangesNotCurrent();
String relatedChangesSubject();
+ String relatedChangesTabPanel();
String registerScreenExplain();
String registerScreenNextLinks();
String registerScreenSection();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java
index f98e8b4..0d46f8f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java
@@ -330,18 +330,27 @@
final native boolean has_revision_number()
/*-{ return this.hasOwnProperty('_revision_number') }-*/;
+ final native boolean has_current_revision_number()
+ /*-{ return this.hasOwnProperty('_current_revision_number') }-*/;
+
final native int _change_number()
/*-{ return this._change_number }-*/;
final native int _revision_number()
/*-{ return this._revision_number }-*/;
+ final native int _current_revision_number()
+ /*-{ return this._current_revision_number }-*/;
+
final native void set_change_number(int n)
/*-{ this._change_number=n; }-*/;
final native void set_revision_number(int n)
/*-{ this._revision_number=n; }-*/;
+ final native void set_current_revision_number(int n)
+ /*-{ this._current_revision_number=n; }-*/;
+
protected ChangeAndCommit() {
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java
index 162471e..5e3cb03 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java
@@ -17,6 +17,7 @@
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.GitwebLink;
import com.google.gerrit.client.change.RelatedChanges.ChangeAndCommit;
+import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -278,6 +279,18 @@
}
sb.closeTd();
+ sb.openTd();
+ GitwebLink gw = Gerrit.getGitwebLink();
+ if (gw != null && (!info.has_change_number() || !info.has_revision_number())) {
+ sb.addStyleName(Gerrit.RESOURCES.css().relatedChangesGitweb());
+ sb.setAttribute("title", gw.getLinkName());
+ } else if (info.has_current_revision_number() && info.has_revision_number()
+ && info._current_revision_number() != info._revision_number()) {
+ sb.addStyleName(Gerrit.RESOURCES.css().relatedChangesNotCurrent());
+ sb.setAttribute("title", Util.C.notCurrent());
+ }
+ sb.closeTd();
+
sb.closeTr();
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBoxUi.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBoxUi.css
index 351442b..ffce7e6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBoxUi.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBoxUi.css
@@ -25,6 +25,11 @@
box-shadow: 3px 3px 3px #888888;
margin-bottom: 5px;
margin-right: 5px;
+ -webkit-touch-callout: initial;
+ -webkit-user-select: initial;
+ -khtml-user-select: initial;
+ -moz-user-select: initial;
+ -ms-user-select: initial;
}
.header { cursor: pointer; }
@@ -80,3 +85,16 @@
white-space: nowrap;
color: #fff;
}
+
+@sprite .go_prev {
+ gwt-image: "go_prev";
+ display: inline-block;
+}
+@sprite .go_next {
+ gwt-image: "go_next";
+ display: inline-block;
+}
+@sprite .go_up {
+ gwt-image: "go_up";
+ display: inline-block;
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java
index 17bacc6..e4ddebd 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java
@@ -37,6 +37,7 @@
private static final Binder uiBinder = GWT.create(Binder.class);
interface DiffTableStyle extends CssResource {
+ String insertCommentIcon();
String fullscreen();
String intralineBg();
String diff();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml
index 02bb499..f314849 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml
@@ -23,11 +23,24 @@
@external .cm-keymap-fat-cursor, CodeMirror-cursor;
@external .cm-searching, .cm-trailingspace, .cm-tab;
+ .insertCommentIcon {
+ cursor: pointer;
+ position: absolute;
+ z-index: 150;
+ }
.fullscreen {
+ background-color: #f7f7f7;
border-bottom: 1px solid #ddd;
}
- .difftable { max-width: 1484px; }
+ .difftable {
+ max-width: 1484px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ }
.difftable .CodeMirror-lines { padding: 0; }
.difftable .CodeMirror pre {
padding: 0;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
index b2a6fd9..9292463 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
@@ -34,6 +34,7 @@
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Visibility;
+import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.uibinder.client.UiBinder;
@@ -43,6 +44,7 @@
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
@@ -52,6 +54,9 @@
class Header extends Composite {
interface Binder extends UiBinder<HTMLPanel, Header> {}
private static final Binder uiBinder = GWT.create(Binder.class);
+ static {
+ Resources.I.style().ensureInjected();
+ }
@UiField CheckBox reviewed;
@UiField Element project;
@@ -62,6 +67,7 @@
@UiField InlineHyperlink prev;
@UiField InlineHyperlink up;
@UiField InlineHyperlink next;
+ @UiField Image preferences;
private final KeyCommandSet keys;
private final PatchSet.Id base;
@@ -70,6 +76,7 @@
private boolean hasPrev;
private boolean hasNext;
private String nextPath;
+ private PreferencesAction prefsAction;
Header(KeyCommandSet keys, PatchSet.Id base, PatchSet.Id patchSetId,
String path) {
@@ -151,10 +158,15 @@
}
}
- void set(ChangeInfo info) {
+ void setChangeInfo(ChangeInfo info) {
project.setInnerText(info.project());
}
+ void init(PreferencesAction pa) {
+ prefsAction = pa;
+ prefsAction.setPartner(preferences);
+ }
+
void setReviewed(boolean r) {
reviewed.setValue(r, true);
}
@@ -176,6 +188,11 @@
}
}
+ @UiHandler("preferences")
+ void onPreferences(ClickEvent e) {
+ prefsAction.show();
+ }
+
private String url(FileInfo info) {
return info.binary()
? Dispatcher.toUnified(base, patchSetId, info.path())
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
index 306109c7..b812f63 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
@@ -18,9 +18,12 @@
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:x='urn:import:com.google.gerrit.client.ui'>
+ <ui:with field='res' type='com.google.gerrit.client.diff.Resources'/>
<ui:style>
.header {
position: relative;
+ height: 16px;
+ line-height: 16px;
max-width: 1484px;
}
.reviewed input {
@@ -29,12 +32,13 @@
vertical-align: middle;
}
.path {
- white-space: no-wrap;
+ white-space: nowrap;
}
.navigation {
position: absolute;
top: 0;
right: 15px;
+ height: 16px;
font-family: Arial Unicode MS, sans-serif;
}
.nodiff {
@@ -56,12 +60,18 @@
</span>
<div class='{style.navigation}'>
- <x:InlineHyperlink ui:field='prev'>⇦</x:InlineHyperlink>
- <x:InlineHyperlink ui:field='up' title='Up to change (Shortcut: u)'>
+ <x:InlineHyperlink ui:field='prev' styleName='{res.style.go_prev}'/>
+ <x:InlineHyperlink ui:field='up'
+ styleName='{res.style.go_up}'
+ title='Up to change (Shortcut: u)'>
<ui:attribute name='title'/>
- ⇧
</x:InlineHyperlink>
- <x:InlineHyperlink ui:field='next'>⇨</x:InlineHyperlink>
+ <x:InlineHyperlink ui:field='next' styleName='{res.style.go_next}'/>
+ <g:Image ui:field='preferences'
+ resource='{res.gear}'
+ title='Diff preferences (Shortcut: ,)'>
+ <ui:attribute name='title'/>
+ </g:Image>
</div>
</g:HTMLPanel>
-</ui:UiBinder>
\ No newline at end of file
+</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java
index 68a24f5..d5d3d8d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java
@@ -19,12 +19,14 @@
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
+import com.google.gwt.user.client.ui.Widget;
class PreferencesAction {
private final SideBySide2 view;
private final DiffPreferences prefs;
private PopupPanel popup;
private PreferencesBox current;
+ private Widget partner;
PreferencesAction(SideBySide2 view, DiffPreferences prefs) {
this.view = view;
@@ -50,6 +52,7 @@
popup = new PopupPanel(true, false);
popup.setStyleName(current.style.dialog());
popup.add(current);
+ popup.addAutoHidePartner(partner.getElement());
popup.addCloseHandler(new CloseHandler<PopupPanel>() {
@Override
public void onClose(CloseEvent<PopupPanel> event) {
@@ -61,7 +64,7 @@
popup.setPopupPositionAndShow(new PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
- popup.setPopupPosition(390, 120);
+ popup.setPopupPosition(300, 120);
}
});
current.setFocus(true);
@@ -74,4 +77,8 @@
current = null;
}
}
+
+ void setPartner(Widget w) {
+ partner = w;
+ }
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java
index b7840c2..5356f2c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java
@@ -17,12 +17,17 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
+import com.google.gwt.resources.client.ImageResource;
/** Resources used by diff. */
interface Resources extends ClientBundle {
static final Resources I = GWT.create(Resources.class);
@Source("CommentBoxUi.css") Style style();
+ @Source("go-prev.png") ImageResource go_prev();
+ @Source("go-next.png") ImageResource go_next();
+ @Source("go-up.png") ImageResource go_up();
+ @Source("gear.png") ImageResource gear();
interface Style extends CssResource {
String commentBox();
@@ -30,5 +35,9 @@
String header();
String summary();
String date();
+
+ String go_prev();
+ String go_next();
+ String go_up();
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
index fea1909..7d16915 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
@@ -54,7 +54,10 @@
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Style;
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.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
@@ -65,6 +68,7 @@
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.GlobalKey;
@@ -73,6 +77,7 @@
import com.google.gwtexpui.globalkey.client.ShowHelpCommand;
import net.codemirror.lib.CodeMirror;
+import net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler;
import net.codemirror.lib.CodeMirror.GutterClickHandler;
import net.codemirror.lib.CodeMirror.LineClassWhere;
import net.codemirror.lib.CodeMirror.LineHandle;
@@ -83,6 +88,7 @@
import net.codemirror.lib.LineCharacter;
import net.codemirror.lib.LineWidget;
import net.codemirror.lib.ModeInjector;
+import net.codemirror.lib.Rect;
import net.codemirror.lib.TextMarker;
import net.codemirror.lib.TextMarker.FromTo;
@@ -226,7 +232,7 @@
JsArray<RevisionInfo> list = info.revisions().values();
RevisionInfo.sortRevisionInfoByNumber(list);
diffTable.setUpPatchSetNav(list, diff);
- header.set(info);
+ header.setChangeInfo(info);
}}));
ConfigInfoCache.get(changeId, group.addFinal(
@@ -314,6 +320,7 @@
}
private void registerCmEvents(final CodeMirror cm) {
+ cm.on("beforeSelectionChange", onSelectionChange(cm));
cm.on("cursorActivity", updateActiveLine(cm));
cm.on("gutterClick", onGutterClick(cm));
cm.on("renderLine", resizeLinePadding(getSideFromCm(cm)));
@@ -399,6 +406,47 @@
.on("Shift-Right", flipCursorSide(cm, false)));
}
+ private BeforeSelectionChangeHandler onSelectionChange(final CodeMirror cm) {
+ return new BeforeSelectionChangeHandler() {
+ private Image icon;
+
+ @Override
+ public void handle(CodeMirror cm, LineCharacter anchor, LineCharacter head) {
+ if (anchor == head
+ || (anchor.getLine() == head.getLine()
+ && anchor.getCh() == head.getCh())) {
+ if (icon != null) {
+ icon.setVisible(false);
+ }
+ return;
+ } else if (icon == null) {
+ init(anchor);
+ }
+
+ icon.setVisible(true);
+ Rect r = cm.charCoords(head, "local");
+ Style s = icon.getElement().getStyle();
+ s.setTop((int) (r.top() - icon.getOffsetHeight() + 2), Unit.PX);
+ s.setLeft((int) (r.right() - icon.getOffsetWidth() / 2), Unit.PX);
+ }
+
+ private void init(LineCharacter anchor) {
+ icon = new Image(Gerrit.RESOURCES.draftComments());
+ icon.setTitle(PatchUtil.C.commentInsert());
+ icon.setStyleName(DiffTable.style.insertCommentIcon());
+ icon.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ icon.setVisible(false);
+ insertNewDraft(cm).run();
+ }
+ });
+ add(icon);
+ cm.addWidget(anchor, icon.getElement(), false);
+ }
+ };
+ }
+
@Override
public void registerKeys() {
super.registerKeys();
@@ -533,6 +581,7 @@
prefsAction = new PreferencesAction(this, prefs);
scrollingGlue = GWT.create(ScrollSynchronizer.class);
scrollingGlue.init(diffTable, cmA, cmB, mapper);
+ header.init(prefsAction);
resizeHandler = Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
@@ -1285,6 +1334,7 @@
if (cm.somethingSelected()) {
lineActiveBoxMap.put(handle,
addNewDraft(cm, line, fromTo.getTo().getLine() == line ? fromTo : null));
+ cm.setSelection(cm.getCursor());
} else if (box == null) {
lineActiveBoxMap.put(handle, addNewDraft(cm, line, null));
} else if (box instanceof DraftBox) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java
index 0f9a5cb..4adb9cc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java
@@ -133,6 +133,7 @@
void expandAll() {
clearMarkerAndWidget();
removeFromParent();
+ updateSelection();
}
private void expandBefore() {
@@ -148,6 +149,7 @@
.set("noHScroll", true);
setWidget(cm.addLineWidget(newStart - 1, getElement(), config));
updateSkipNum();
+ updateSelection();
}
private void expandAfter() {
@@ -167,6 +169,14 @@
setWidget(cm.addLineWidget(newEnd + 1, getElement(), config));
}
updateSkipNum();
+ updateSelection();
+ }
+
+ private void updateSelection() {
+ if (cm.somethingSelected()) {
+ FromTo sel = cm.getSelectedRange();
+ cm.setSelection(sel.getFrom(), sel.getTo());
+ }
}
@UiHandler("skipNum")
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/gear.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/gear.png
new file mode 100644
index 0000000..d90ab66
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/gear.png
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-next.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-next.png
new file mode 100644
index 0000000..6ef8de7
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-next.png
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-prev.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-prev.png
new file mode 100644
index 0000000..659cd90
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-prev.png
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-up.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-up.png
new file mode 100644
index 0000000..fa9a7d7
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/go-up.png
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 9c8ec57..029dd3b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -1642,3 +1642,11 @@
.relatedChangesTabPanel .gwt-TabBarItem-disabled {
display: none;
}
+.relatedChangesNotCurrent:after {
+ content: '\25CF'; /* circle */
+ color: #FFA62F; /* orange */
+}
+.relatedChangesGitweb:after {
+ content: '\25CF'; /* circle */
+ color: #000;
+}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java
index 6ff6f72..712f268 100644
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java
+++ b/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java
@@ -138,6 +138,10 @@
return this.heightAtLine(line, mode);
}-*/;
+ public final native Rect charCoords(LineCharacter pos, String mode) /*-{
+ return this.charCoords(pos, mode);
+ }-*/;
+
public final native CodeMirrorDoc getDoc() /*-{
return this.getDoc();
}-*/;
@@ -197,6 +201,12 @@
}));
}-*/;
+ public final native void on(String event, BeforeSelectionChangeHandler handler) /*-{
+ this.on(event, $entry(function(cm, e) {
+ handler.@net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler::handle(Lnet/codemirror/lib/CodeMirror;Lnet/codemirror/lib/LineCharacter;Lnet/codemirror/lib/LineCharacter;)(cm,e.anchor,e.head);
+ }));
+ }-*/;
+
public final native LineCharacter getCursor() /*-{
return this.getCursor();
}-*/;
@@ -209,6 +219,14 @@
return FromTo.create(getCursor("start"), getCursor("end"));
}
+ public final native void setSelection(LineCharacter anchor) /*-{
+ this.setSelection(anchor);
+ }-*/;
+
+ public final native void setSelection(LineCharacter anchor, LineCharacter head) /*-{
+ this.setSelection(anchor, head);
+ }-*/;
+
public final native void setCursor(LineCharacter lineCh) /*-{
this.setCursor(lineCh);
}-*/;
@@ -341,4 +359,8 @@
public void handle(CodeMirror instance, int line, String gutter,
NativeEvent clickEvent);
}
+
+ public interface BeforeSelectionChangeHandler {
+ public void handle(CodeMirror instance, LineCharacter anchor, LineCharacter head);
+ }
}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java
new file mode 100644
index 0000000..5691d9f
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java
@@ -0,0 +1,28 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package net.codemirror.lib;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/** {left, right, top, bottom} objects used within CodeMirror. */
+public class Rect extends JavaScriptObject {
+ public final native double left() /*-{ return this.left }-*/;
+ public final native double right() /*-{ return this.right }-*/;
+ public final native double top() /*-{ return this.top }-*/;
+ public final native double bottom() /*-{ return this.bottom }-*/;
+
+ protected Rect() {
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
index d804f38..7ac872d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
@@ -287,12 +287,15 @@
CommitInfo commit;
Integer _changeNumber;
Integer _revisionNumber;
+ Integer _currentRevisionNumber;
ChangeAndCommit(@Nullable Change change, @Nullable PatchSet ps, RevCommit c) {
if (change != null) {
changeId = change.getKey().get();
_changeNumber = change.getChangeId();
_revisionNumber = ps != null ? ps.getPatchSetId() : null;
+ PatchSet.Id curr = change.currentPatchSetId();
+ _currentRevisionNumber = curr != null ? curr.get() : null;
}
commit = new CommitInfo();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index be4b0ce..b7b34b1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -1710,6 +1710,7 @@
if (newCommit == priorCommit) {
// Ignore requests to make the change its current state.
skip = true;
+ reject(inputCommand, "commit already exists");
return false;
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateBranchCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateBranchCommand.java
new file mode 100644
index 0000000..16ffe28
--- /dev/null
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateBranchCommand.java
@@ -0,0 +1,59 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.sshd.commands;
+
+import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.api.projects.BranchApi;
+import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.server.project.CreateBranch;
+import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.sshd.CommandMetaData;
+import com.google.gerrit.sshd.SshCommand;
+import com.google.inject.Inject;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+import java.io.IOException;
+
+/** Create a new branch. **/
+@CommandMetaData(name = "create-branch", description = "Create a new branch")
+final public class CreateBranchCommand extends SshCommand {
+
+ @Argument(index = 0, required = true, metaVar = "PROJECT", usage = "name of the project")
+ private ProjectControl project;
+
+ @Argument(index = 1, required = true, metaVar = "NAME", usage = "name of branch to be created")
+ private String name;
+
+ @Argument(index = 2, required = true, metaVar = "REVISION", usage = "base revision of the new branch")
+ private String revision;
+
+ @Inject
+ GerritApi gApi;
+
+ @Override
+ protected void run() throws UnloggedFailure {
+ try {
+ BranchInput in = new BranchInput();
+ in.revision = revision;
+ gApi.projects().name(project.getProject().getNameKey().get())
+ .branch(name).create(in);
+ } catch (RestApiException e) {
+ throw new UnloggedFailure(1, "fatal: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java
index a8d5c4d..a79e862 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java
@@ -31,6 +31,7 @@
command(gerrit, CreateGroupCommand.class);
command(gerrit, RenameGroupCommand.class);
command(gerrit, CreateProjectCommand.class);
+ command(gerrit, CreateBranchCommand.class);
command(gerrit, AdminQueryShell.class);
command(gerrit, SetReviewersCommand.class);
command(gerrit, Receive.class);