From b799d545f37f7123aaa1ee1d0ff3b61f1f3cc8c2 Mon Sep 17 00:00:00 2001
From: David Ostrovsky <david@ostrovsky.org>
Date: Thu, 10 Apr 2014 18:58:08 -0400
Subject: [PATCH] Add review SSH command

---
 src/main/java/com/gitblit/transport/ssh/SshDaemon.java              |    2 +
 src/main/java/com/gitblit/models/TicketModel.java                   |   13 ++++++
 src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java |   87 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 1 deletions(-)

diff --git a/src/main/java/com/gitblit/models/TicketModel.java b/src/main/java/com/gitblit/models/TicketModel.java
index aced6d7..f843e99 100644
--- a/src/main/java/com/gitblit/models/TicketModel.java
+++ b/src/main/java/com/gitblit/models/TicketModel.java
@@ -35,6 +35,7 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.regex.Matcher;
@@ -1152,7 +1153,8 @@
 	}
 
 	public static enum Score {
-		approved(2), looks_good(1), not_reviewed(0), needs_improvement(-1), vetoed(-2);
+		approved(2), looks_good(1), not_reviewed(0), needs_improvement(-1), vetoed(
+				-2);
 
 		final int value;
 
@@ -1168,6 +1170,15 @@
 		public String toString() {
 			return name().toLowerCase().replace('_', ' ');
 		}
+
+		public static Score fromScore(int score) {
+			for (Score s : values()) {
+				if (s.getValue() == score) {
+					return s;
+				}
+			}
+			throw new NoSuchElementException(String.valueOf(score));
+		}
 	}
 
 	public static enum Field {
diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
index f2e1db7..4a2239b 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
@@ -44,6 +44,7 @@
 import com.gitblit.transport.ssh.commands.CreateRepository;
 import com.gitblit.transport.ssh.commands.DispatchCommand;
 import com.gitblit.transport.ssh.commands.Receive;
+import com.gitblit.transport.ssh.commands.ReviewCommand;
 import com.gitblit.transport.ssh.commands.SetAccountCommand;
 import com.gitblit.transport.ssh.commands.Upload;
 import com.gitblit.transport.ssh.commands.VersionCommand;
@@ -134,6 +135,7 @@
 		gitblitCmd.registerCommand(CreateRepository.class);
 		gitblitCmd.registerCommand(VersionCommand.class);
 		gitblitCmd.registerCommand(SetAccountCommand.class);
+		gitblitCmd.registerCommand(ReviewCommand.class);
 
 		DispatchCommand gitCmd = new DispatchCommand();
 		gitCmd.registerCommand(Upload.class);
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java
new file mode 100644
index 0000000..9ce7331
--- /dev/null
+++ b/src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * 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.gitblit.transport.ssh.commands;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+import com.gitblit.models.TicketModel.Change;
+import com.gitblit.models.TicketModel.Patchset;
+import com.gitblit.models.TicketModel.Score;
+import com.gitblit.models.UserModel;
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.wicket.GitBlitWebSession;
+
+@CommandMetaData(name = "review", description = "Verify, approve and/or submit one or more patch sets")
+public class ReviewCommand extends SshCommand {
+
+	private final static short REV_ID_LEN = 40;
+	private final Set<Patchset> patchSets = new HashSet<Patchset>();
+
+	@Argument(index = 0, required = true, multiValued = true, metaVar = "{COMMIT | CHANGE,PATCHSET}", usage = "list of commits or patch sets to review")
+	void addPatchSetId(final String token) {
+		try {
+			patchSets.add(parsePatchSet(token));
+		} catch (UnloggedFailure e) {
+			throw new IllegalArgumentException(e.getMessage(), e);
+		}
+	}
+
+	@Option(name = "--project", required = true, aliases = "-p", usage = "project containing the specified patch set(s)")
+	private String project;
+
+	@Option(name = "--message", aliases = "-m", usage = "cover message to publish on change(s)", metaVar = "MESSAGE")
+	private String changeComment;
+
+	@Option(name = "--vote", aliases = "-v", usage = "vote on this patch set", metaVar = "VOTE")
+	private int vote;
+
+	@Option(name = "--submit", aliases = "-s", usage = "submit the specified patch set(s)")
+	private boolean submitChange;
+
+	@Override
+	public void run() throws UnloggedFailure {
+		UserModel user = GitBlitWebSession.get().getUser();
+		for (Patchset ps : patchSets) {			
+			// review
+			Change change = new Change(user.username);			
+			change.review(ps, Score.fromScore(vote), false);
+			// TODO(davido): add patchset comment
+			if (submitChange) {
+				// TODO(davido): merge (when desired and the change is mergeable)				
+			}
+		}
+	}
+
+	private Patchset parsePatchSet(String ps) throws UnloggedFailure {
+		// By commit?
+		//
+		if (ps.matches("^([0-9a-fA-F]{4," + REV_ID_LEN + "})$")) {
+			// TODO; parse
+		}
+
+		// By older style change,patchset?
+		//
+		if (ps.matches("^[1-9][0-9]*,[1-9][0-9]*$")) {
+			// TODO: parse
+		}
+
+		throw new UnloggedFailure(1, "fatal: Cannot parse patchset: " + ps);
+	}
+}

--
Gitblit v1.9.1