diff options
author | James Moger <james.moger@gitblit.com> | 2011-04-04 09:10:51 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2011-04-04 09:10:51 -0400 |
commit | 5fe7df81eb38dc66f2cfc4bf1973863a19f55cf2 (patch) | |
tree | 3f1b1b3f953aa8a5ed60e149043598fbdaf4d42f /src/com | |
download | gitblit-5fe7df81eb38dc66f2cfc4bf1973863a19f55cf2.tar.gz gitblit-5fe7df81eb38dc66f2cfc4bf1973863a19f55cf2.zip |
Initial import of Git:Blit.
Change-Id: Ifce000c85c8947c3a768e782c841e41a8953d314
Diffstat (limited to 'src/com')
61 files changed, 3947 insertions, 0 deletions
diff --git a/src/com/gitblit/Build.java b/src/com/gitblit/Build.java new file mode 100644 index 00000000..08202ba1 --- /dev/null +++ b/src/com/gitblit/Build.java @@ -0,0 +1,168 @@ +package com.gitblit;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class Build {
+
+ public static void main(String... args) {
+ runtime();
+ compiletime();
+ }
+
+ public static void runtime() {
+ downloadFromMaven(MavenObject.JCOMMANDER);
+ downloadFromMaven(MavenObject.JETTY);
+ downloadFromMaven(MavenObject.SERVLET);
+ downloadFromMaven(MavenObject.SLF4JAPI);
+ downloadFromMaven(MavenObject.SLF4LOG4J);
+ downloadFromMaven(MavenObject.LOG4J);
+ downloadFromMaven(MavenObject.WICKET);
+ downloadFromMaven(MavenObject.WICKET_EXT);
+ downloadFromMaven(MavenObject.WICKET_AUTH_ROLES);
+ }
+
+ public static void compiletime() {
+ downloadFromMaven(MavenObject.JUNIT);
+ }
+
+ /**
+ * Download a file from a Maven repository.
+ *
+ * @param mo
+ * the maven object to download.
+ * @return
+ */
+ private static File downloadFromMaven(MavenObject mo) {
+ File targetFile = mo.getLocalFile("ext");
+ if (targetFile.exists()) {
+ return targetFile;
+ }
+
+ String mavenURL = "http://repo1.maven.org/maven2/" + mo.getRepositoryPath();
+ if (!targetFile.getAbsoluteFile().getParentFile().exists()) {
+ boolean success = targetFile.getAbsoluteFile().getParentFile().mkdirs();
+ if (!success) {
+ throw new RuntimeException("Failed to create destination folder structure!");
+ }
+ }
+ ByteArrayOutputStream buff = new ByteArrayOutputStream();
+ try {
+ System.out.println("Downloading " + mavenURL);
+ URL url = new URL(mavenURL);
+ InputStream in = new BufferedInputStream(url.openStream());
+ long last = System.currentTimeMillis();
+ int len = 0;
+ while (true) {
+ long now = System.currentTimeMillis();
+ if (now > last + 200) {
+ System.out.println(" downloaded " + len + " bytes");
+ last = now;
+ }
+ int x = in.read();
+ len++;
+ if (x < 0) {
+ break;
+ }
+ buff.write(x);
+ }
+ in.close();
+ } catch (IOException e) {
+ throw new RuntimeException("Error downloading " + mavenURL + " to " + targetFile, e);
+ }
+ byte[] data = buff.toByteArray();
+ String got = getSHA1(data);
+ if (mo.sha1 != null && !got.equals(mo.sha1)) {
+ throw new RuntimeException("SHA1 checksum mismatch; got: " + got);
+ }
+ try {
+ RandomAccessFile ra = new RandomAccessFile(targetFile, "rw");
+ ra.write(data);
+ ra.setLength(data.length);
+ ra.close();
+ } catch (IOException e) {
+ throw new RuntimeException("Error writing to file " + targetFile, e);
+ }
+ return targetFile;
+ }
+
+ /**
+ * Generate the SHA1 checksum of a byte array.
+ *
+ * @param data
+ * the byte array
+ * @return the SHA1 checksum
+ */
+ private static String getSHA1(byte[] data) {
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ byte[] value = md.digest(data);
+ StringBuilder buff = new StringBuilder(value.length * 2);
+ for (byte c : value) {
+ int x = c & 0xff;
+ buff.append(Integer.toString(x >> 4, 16)).append(Integer.toString(x & 0xf, 16));
+ }
+ return buff.toString();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static class MavenObject {
+
+ public static final MavenObject JCOMMANDER = new MavenObject("jCommander", "com/beust", "jcommander", "1.17", "219a3540f3b27d7cc3b1d91d6ea046cd8723290e");
+
+ public static final MavenObject JETTY = new MavenObject("Jetty", "org/eclipse/jetty/aggregate", "jetty-all", "7.2.2.v20101205", "b9b7c812a732721c427e208c54fbb71ca17a2ee1");
+
+ public static final MavenObject SERVLET = new MavenObject("Servlet 2.5", "javax/servlet", "servlet-api", "2.5", "5959582d97d8b61f4d154ca9e495aafd16726e34");
+
+ public static final MavenObject SLF4JAPI = new MavenObject("SLF4J API", "org/slf4j", "slf4j-api", "1.6.1", "6f3b8a24bf970f17289b234284c94f43eb42f0e4");
+
+ public static final MavenObject SLF4LOG4J = new MavenObject("SLF4J LOG4J", "org/slf4j", "slf4j-log4j12", "1.6.1", "bd245d6746cdd4e6203e976e21d597a46f115802");
+
+ public static final MavenObject LOG4J = new MavenObject("Apache LOG4J", "log4j", "log4j", "1.2.16", "7999a63bfccbc7c247a9aea10d83d4272bd492c6");
+
+ public static final MavenObject WICKET = new MavenObject("Apache Wicket", "org/apache/wicket", "wicket", "1.4.17", "39815e37a6f56465b2d2c3d3017c4f3bf17db50a");
+
+ public static final MavenObject WICKET_EXT = new MavenObject("Apache Wicket Extensions", "org/apache/wicket", "wicket-extensions", "1.4.17", "01111d0dbffdc425581b006a43864c22797ce72a");
+
+ public static final MavenObject WICKET_AUTH_ROLES = new MavenObject("Apache Wicket Auth Roles", "org/apache/wicket", "wicket-auth-roles", "1.4.17", "86d20ff32f62d3026213ff11a78555da643bc676");
+
+ public static final MavenObject JUNIT = new MavenObject("JUnit", "junit", "junit", "3.8.2", "07e4cde26b53a9a0e3fe5b00d1dbbc7cc1d46060");
+
+ public final String name;
+ public final String group;
+ public final String artifact;
+ public final String version;
+ public final String sha1;
+
+ private MavenObject(String name, String group, String artifact, String version, String sha1) {
+ this.name = name;
+ this.group = group;
+ this.artifact = artifact;
+ this.version = version;
+ this.sha1 = sha1;
+ }
+
+ private String getRepositoryPath() {
+ return group + "/" + artifact + "/" + version + "/" + artifact + "-" + version + ".jar";
+ }
+
+ private File getLocalFile(String basePath) {
+ return new File(basePath, artifact + "-" + version + ".jar");
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java new file mode 100644 index 00000000..5de10cdf --- /dev/null +++ b/src/com/gitblit/Constants.java @@ -0,0 +1,12 @@ +package com.gitblit;
+
+public class Constants {
+
+ public final static String NAME = "Git:Blit";
+
+ public final static String VERSION = "0.11.3";
+
+ public static String getRunningVersion() {
+ return NAME + " v" + VERSION;
+ }
+}
diff --git a/src/com/gitblit/GitBlitServer.java b/src/com/gitblit/GitBlitServer.java new file mode 100644 index 00000000..ae542e8d --- /dev/null +++ b/src/com/gitblit/GitBlitServer.java @@ -0,0 +1,393 @@ +package com.gitblit;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.PatternLayout;
+import org.apache.wicket.protocol.http.ContextParamWebApplicationFactory;
+import org.apache.wicket.protocol.http.WicketFilter;
+import org.eclipse.jetty.http.security.Constraint;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.HashLoginService;
+import org.eclipse.jetty.security.authentication.BasicAuthenticator;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.bio.SocketConnector;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslConnector;
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslSocketConnector;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jgit.http.server.GitServlet;
+
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.ParameterException;
+import com.beust.jcommander.Parameters;
+import com.gitblit.wicket.GitBlitWebApp;
+
+public class GitBlitServer {
+
+ private final static Logger logger = Log.getLogger(GitBlitServer.class.getSimpleName());
+ private final static String border_star = "***********************************************************";
+ private static boolean debugMode = false;
+
+ public static boolean isDebugMode() {
+ return debugMode;
+ }
+
+ public static void main(String[] args) {
+ Params params = new Params();
+ JCommander jc = new JCommander(params);
+ try {
+ jc.parse(args);
+ if (params.help)
+ usage(jc, null);
+ } catch (ParameterException t) {
+ usage(jc, t);
+ }
+
+ if (params.stop)
+ stop(params);
+ else
+ start(params);
+ }
+
+ private static void usage(JCommander jc, ParameterException t) {
+ System.out.println(border_star);
+ System.out.println(Constants.getRunningVersion());
+ System.out.println(border_star);
+ System.out.println();
+ if (t != null) {
+ System.out.println(t.getMessage());
+ System.out.println();
+ }
+ if (jc != null) {
+ jc.usage();
+ System.out.println("\nExample:\n java -server -Xmx1024M -jar go-git-go.jar --repos c:\\git --port 80 --securePort 443");
+ }
+ System.exit(0);
+ }
+
+ /**
+ * Stop Server.
+ */
+ public static void stop(Params params) {
+ try {
+ Socket s = new Socket(InetAddress.getByName("127.0.0.1"), params.shutdownPort);
+ OutputStream out = s.getOutputStream();
+ System.out.println("Sending Shutdown Request to " + Constants.NAME);
+ out.write(("\r\n").getBytes());
+ out.flush();
+ s.close();
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Start Server.
+ */
+ private static void start(Params params) {
+ PatternLayout layout = new PatternLayout(StoredSettings.getString("log4jPattern", "%-5p %d{MM-dd HH:mm:ss.SSS} %-20.20c{1} %m%n"));
+ org.apache.log4j.Logger rootLogger = org.apache.log4j.Logger.getRootLogger();
+ rootLogger.addAppender(new ConsoleAppender(layout));
+
+ logger.info(border_star);
+ logger.info(Constants.getRunningVersion());
+ logger.info(border_star);
+
+ String osname = System.getProperty("os.name");
+ String osversion = System.getProperty("os.version");
+ logger.info("Running on " + osname + " (" + osversion + ")");
+
+ if (params.debug) {
+ logger.warn("DEBUG Mode");
+ }
+
+ // Determine port connectors
+ List<Connector> connectors = new ArrayList<Connector>();
+ if (params.port > 0) {
+ Connector httpConnector = createConnector(params.useNIO, params.port);
+ connectors.add(httpConnector);
+ }
+
+ if (params.securePort > 0) {
+ if (new File("keystore").exists()) {
+ Connector secureConnector = createSSLConnector(params.useNIO, params.securePort, params.storePassword);
+ connectors.add(secureConnector);
+ } else {
+ logger.warn("Failed to find Keystore? Did you run \"makekeystore\"?");
+ logger.warn("SSL connector DISABLED.");
+ }
+ }
+
+ // tempDir = Directory where...
+ // * WebApp is expanded
+ //
+ File tempDir = new File(params.temp);
+ if (tempDir.exists())
+ deleteRecursively(tempDir);
+ tempDir.mkdirs();
+
+ Server server = new Server();
+ server.setStopAtShutdown(true);
+ server.setConnectors(connectors.toArray(new Connector[connectors.size()]));
+
+ // Get the execution path of this class
+ // We use this to set the WAR path.
+ ProtectionDomain protectionDomain = GitBlitServer.class.getProtectionDomain();
+ URL location = protectionDomain.getCodeSource().getLocation();
+
+ // Root WebApp Context
+ WebAppContext rootContext = new WebAppContext();
+ rootContext.setContextPath("/");
+ rootContext.setServer(server);
+ rootContext.setWar(location.toExternalForm());
+ rootContext.setTempDirectory(tempDir);
+
+ // Wicket Filter
+ String wicketPathSpec = "/*";
+ FilterHolder wicketFilter = new FilterHolder(WicketFilter.class);
+ wicketFilter.setInitParameter(ContextParamWebApplicationFactory.APP_CLASS_PARAM, GitBlitWebApp.class.getName());
+ wicketFilter.setInitParameter(WicketFilter.FILTER_MAPPING_PARAM, wicketPathSpec);
+ rootContext.addFilter(wicketFilter, wicketPathSpec, FilterMapping.DEFAULT);
+
+ // GIT Servlet
+ String gitServletPathSpec = "/git/*";
+ ServletHolder gitServlet = rootContext.addServlet(GitServlet.class, gitServletPathSpec);
+ gitServlet.setInitParameter("base-path", params.repositoriesFolder);
+ gitServlet.setInitParameter("export-all", params.exportAll ? "1" : "0");
+
+ String realmUsers = params.realmFile;
+
+ // Authentication Realm
+ Handler handler;
+ if (realmUsers != null && new File(realmUsers).exists() && params.authenticateAccess) {
+ List<String> list = StoredSettings.getStrings("gitRoles");
+ String[] roles;
+ if (list.size() == 0) {
+ roles = new String[] { "*" };
+ } else {
+ roles = list.toArray(new String[list.size()]);
+ }
+ logger.info("Authentication required for GIT access");
+ logger.info("Setting up realm from " + realmUsers);
+ HashLoginService loginService = new HashLoginService(Constants.NAME, realmUsers);
+
+ Constraint constraint = new Constraint();
+ constraint.setName("auth");
+ constraint.setAuthenticate(true);
+ constraint.setRoles(roles);
+
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setPathSpec(gitServletPathSpec);
+ mapping.setConstraint(constraint);
+
+ ConstraintSecurityHandler security = new ConstraintSecurityHandler();
+ security.addConstraintMapping(mapping);
+ for (String role : roles) {
+ security.addRole(role);
+ }
+ security.setAuthenticator(new BasicAuthenticator());
+ security.setLoginService(loginService);
+ security.setStrict(false);
+
+ security.setHandler(rootContext);
+
+ handler = security;
+ } else {
+ logger.info("Setting up anonymous access");
+ handler = rootContext;
+ }
+
+ // Set the server's contexts
+ server.setHandler(handler);
+
+ // Start the Server
+ try {
+ if (params.shutdownPort > 0) {
+ Thread shutdownMonitor = new ShutdownMonitorThread(server, params);
+ shutdownMonitor.start();
+ }
+ server.start();
+ server.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(100);
+ }
+ }
+
+ private static Connector createConnector(boolean useNIO, int port) {
+ Connector connector;
+ if (useNIO) {
+ logger.info("Setting up NIO SelectChannelConnector on port " + port);
+ SelectChannelConnector nioconn = new SelectChannelConnector();
+ nioconn.setSoLingerTime(-1);
+ nioconn.setThreadPool(new QueuedThreadPool(20));
+ connector = nioconn;
+ } else {
+ logger.info("Setting up SocketConnector on port " + port);
+ SocketConnector sockconn = new SocketConnector();
+ connector = sockconn;
+ }
+
+ connector.setPort(port);
+ connector.setMaxIdleTime(30000);
+ return connector;
+ }
+
+ private static Connector createSSLConnector(boolean useNIO, int port, String password) {
+ SslConnector connector;
+ if (useNIO) {
+ logger.info("Setting up NIO SslSelectChannelConnector on port " + port);
+ SslSelectChannelConnector ssl = new SslSelectChannelConnector();
+ ssl.setSoLingerTime(-1);
+ ssl.setThreadPool(new QueuedThreadPool(20));
+ connector = ssl;
+ } else {
+ logger.info("Setting up NIO SslSocketConnector on port " + port);
+ SslSocketConnector ssl = new SslSocketConnector();
+ connector = ssl;
+ }
+ connector.setKeystore("keystore");
+ connector.setPassword(password);
+ connector.setPort(port);
+ connector.setMaxIdleTime(30000);
+ return connector;
+ }
+
+ /**
+ * Recursively delete a folder and its contents.
+ *
+ * @param folder
+ */
+ private static void deleteRecursively(File folder) {
+ for (File file : folder.listFiles()) {
+ if (file.isDirectory())
+ deleteRecursively(file);
+ else
+ file.delete();
+ }
+ folder.delete();
+ }
+
+ private static class ShutdownMonitorThread extends Thread {
+
+ private final ServerSocket socket;
+
+ private final Server server;
+
+ public ShutdownMonitorThread(Server server, Params params) {
+ this.server = server;
+ setDaemon(true);
+ setName(Constants.NAME + " Shutdown Monitor");
+ ServerSocket skt = null;
+ try {
+ skt = new ServerSocket(params.shutdownPort, 1, InetAddress.getByName("127.0.0.1"));
+ } catch (Exception e) {
+ logger.warn(e);
+ }
+ socket = skt;
+ }
+
+ @Override
+ public void run() {
+ logger.info("Shutdown Monitor listening on port " + socket.getLocalPort());
+ Socket accept;
+ try {
+ accept = socket.accept();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
+ reader.readLine();
+ logger.info(border_star);
+ logger.info("Stopping " + Constants.NAME);
+ logger.info(border_star);
+ server.stop();
+ server.setStopAtShutdown(false);
+ accept.close();
+ socket.close();
+ } catch (Exception e) {
+ logger.warn("Failed to shutdown Jetty", e);
+ }
+ }
+ }
+
+ @Parameters(separators = " ")
+ private static class Params {
+
+ /*
+ * Server parameters
+ */
+ @Parameter(names = { "-h", "--help" }, description = "Show this help")
+ public Boolean help = false;
+
+ @Parameter(names = { "--stop" }, description = "Stop Server")
+ public Boolean stop = false;
+
+ @Parameter(names = { "--temp" }, description = "Server temp folder")
+ public String temp = StoredSettings.getString("tempFolder", "temp");
+
+ @Parameter(names = { "--debug" }, description = "Run server in DEBUG mode")
+ public Boolean debug = StoredSettings.getBoolean("debug", false);
+
+ /*
+ * GIT Servlet Parameters
+ */
+ @Parameter(names = { "--repos" }, description = "GIT Repositories Folder")
+ public String repositoriesFolder = StoredSettings.getString("repositoriesFolder", "repos");
+
+ @Parameter(names = { "--exportAll" }, description = "Export All Found Repositories")
+ public Boolean exportAll = StoredSettings.getBoolean("exportAll", true);
+
+ /*
+ * Authentication Parameters
+ */
+ @Parameter(names = { "--authenticateAccess" }, description = "Authenticate GIT access")
+ public Boolean authenticateAccess = StoredSettings.getBoolean("authenticateAccess", true);
+
+ @Parameter(names = { "--realm" }, description = "Users Realm Hash File")
+ public String realmFile = StoredSettings.getString("realmFile", "users.properties");
+
+ /*
+ * JETTY Parameters
+ */
+ @Parameter(names = { "--nio" }, description = "Use NIO Connector else use Socket Connector.")
+ public Boolean useNIO = StoredSettings.getBoolean("useNio", true);
+
+ @Parameter(names = "--port", description = "HTTP port for to serve. (port <= 0 will disable this connector)")
+ public Integer port = StoredSettings.getInteger("httpPort", 80);
+
+ @Parameter(names = "--securePort", description = "HTTPS port to serve. (port <= 0 will disable this connector)")
+ public Integer securePort = StoredSettings.getInteger("httpsPort", 443);
+
+ @Parameter(names = "--storePassword", description = "Password for SSL (https) keystore.")
+ public String storePassword = StoredSettings.getString("storePassword", "");
+
+ @Parameter(names = "--shutdownPort", description = "Port for Shutdown Monitor to listen on. (port <= 0 will disable this monitor)")
+ public Integer shutdownPort = StoredSettings.getInteger("shutdownPort", 8081);
+
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/Launcher.java b/src/com/gitblit/Launcher.java new file mode 100644 index 00000000..a55056d5 --- /dev/null +++ b/src/com/gitblit/Launcher.java @@ -0,0 +1,117 @@ +package com.gitblit;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Launch helper class that adds all jars found in the local "lib" folder and
+ * then calls the application main. Using this technique we do not have to
+ * specify a classpath and we can dynamically add jars to the distribution.
+ *
+ */
+public class Launcher {
+
+ public final static boolean debug = false;
+
+ public static void main(String[] args) {
+ if (debug)
+ System.out.println("jcp=" + System.getProperty("java.class.path"));
+
+ ProtectionDomain protectionDomain = Launcher.class.getProtectionDomain();
+ final String launchJar = protectionDomain.getCodeSource().getLocation().toExternalForm();
+ if (debug)
+ System.out.println("launcher=" + launchJar);
+
+ Build.runtime();
+
+ // Load the JARs in the lib and ext folder
+ String[] folders = new String[] { "lib", "ext" };
+ List<File> jars = new ArrayList<File>();
+ for (String folder : folders) {
+ if (folder == null)
+ continue;
+ File libFolder = new File(folder);
+ if (!libFolder.exists())
+ continue;
+ try {
+ libFolder = libFolder.getCanonicalFile();
+ } catch (IOException iox) {
+ }
+ jars.addAll(findJars(libFolder));
+ }
+
+ if (jars.size() == 0) {
+ for (String folder : folders) {
+ File libFolder = new File(folder);
+ System.err.println("Failed to find any JARs in " + libFolder.getPath());
+ }
+ System.exit(-1);
+ } else {
+ for (File jar : jars) {
+ try {
+ addJarFile(jar);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ }
+
+ // Start Server
+ GitBlitServer.main(args);
+ }
+
+ public static List<File> findJars(File folder) {
+ List<File> jars = new ArrayList<File>();
+ if (folder.exists()) {
+ File[] libs = folder.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return !file.isDirectory() && file.getName().toLowerCase().endsWith(".jar");
+ }
+ });
+ if (libs != null && libs.length > 0) {
+ jars.addAll(Arrays.asList(libs));
+ if (debug) {
+ for (File jar : jars)
+ System.out.println("found " + jar);
+ }
+ }
+ }
+ return jars;
+ }
+
+ /**
+ * Parameters of the method to add an URL to the System classes.
+ */
+ private static final Class<?>[] parameters = new Class[] { URL.class };
+
+ /**
+ * Adds a file to the classpath
+ *
+ * @param f
+ * the file to be added
+ * @throws IOException
+ */
+ public static void addJarFile(File f) throws IOException {
+ URL u = f.toURI().toURL();
+ if (debug)
+ System.out.println("load=" + u.toExternalForm());
+ URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+ Class<?> sysclass = URLClassLoader.class;
+ try {
+ Method method = sysclass.getDeclaredMethod("addURL", parameters);
+ method.setAccessible(true);
+ method.invoke(sysloader, new Object[] { u });
+ } catch (Throwable t) {
+ throw new IOException("Error, could not add " + f.getPath() + " to system classloader", t);
+ }
+ }
+}
diff --git a/src/com/gitblit/MakeRepository.java b/src/com/gitblit/MakeRepository.java new file mode 100644 index 00000000..15240f83 --- /dev/null +++ b/src/com/gitblit/MakeRepository.java @@ -0,0 +1,51 @@ +package com.gitblit;
+
+import java.io.File;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.InitCommand;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.ParameterException;
+import com.beust.jcommander.Parameters;
+
+public class MakeRepository {
+
+ public static void main(String... args) throws Exception {
+ Params params = new Params();
+ JCommander jc = new JCommander(params);
+ try {
+ jc.parse(args);
+ if (params.help)
+ jc.usage();
+ } catch (ParameterException t) {
+ jc.usage();
+ }
+
+ File directory = new File(params.create);
+ InitCommand init = new InitCommand();
+ init.setDirectory(directory);
+ init.setBare(true);
+ Git git = init.call();
+ git.getRepository().close();
+ System.out.println("GIT repository " + directory.getCanonicalPath() + " created.");
+ }
+
+ @Parameters(separators = " ")
+ private static class Params {
+
+ /*
+ * Help/Usage
+ */
+ @Parameter(names = { "-h", "--help" }, description = "Show this help")
+ public Boolean help = false;
+
+ /*
+ * Repository to Create
+ */
+ @Parameter(names = { "--create" }, description = "GIT Repository to Create", required = true)
+ public String create = "";
+
+ }
+}
diff --git a/src/com/gitblit/StoredSettings.java b/src/com/gitblit/StoredSettings.java new file mode 100644 index 00000000..d495ad87 --- /dev/null +++ b/src/com/gitblit/StoredSettings.java @@ -0,0 +1,130 @@ +package com.gitblit;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Reads settings file.
+ *
+ */
+public class StoredSettings {
+
+ private static Properties properties = new Properties();
+
+ private static long lastread = 0;
+
+ private static final Logger logger = LoggerFactory.getLogger(StoredSettings.class);
+
+ public static List<String> getAllKeys(String startingWith) {
+ startingWith = startingWith.toLowerCase();
+ List<String> keys = new ArrayList<String>();
+ Properties props = read();
+ for (Object o : props.keySet()) {
+ String key = o.toString().toLowerCase();
+ if (key.startsWith(startingWith)) {
+ keys.add(key);
+ }
+ }
+ return keys;
+ }
+
+ public static boolean getBoolean(String name, boolean defaultValue) {
+ Properties props = read();
+ if (props.containsKey(name)) {
+ try {
+ String value = props.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ return Boolean.parseBoolean(value);
+ }
+ } catch (Exception e) {
+ logger.warn("No override setting for " + name + " using default of " + defaultValue);
+ }
+ }
+ return defaultValue;
+ }
+
+ public static int getInteger(String name, int defaultValue) {
+ Properties props = read();
+ if (props.containsKey(name)) {
+ try {
+ String value = props.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ return Integer.parseInt(value);
+ }
+ } catch (Exception e) {
+ logger.warn("No override setting for " + name + " using default of " + defaultValue);
+ }
+ }
+ return defaultValue;
+ }
+
+ public static String getString(String name, String defaultValue) {
+ Properties props = read();
+ if (props.containsKey(name)) {
+ try {
+ String value = props.getProperty(name);
+ if (value != null) {
+ return value;
+ }
+ } catch (Exception e) {
+ logger.warn("No override setting for " + name + " using default of " + defaultValue);
+ }
+ }
+ return defaultValue;
+ }
+
+ public static List<String> getStrings(String name) {
+ return getStrings(name, " ");
+ }
+
+ public static List<String> getStringsFromValue(String value) {
+ return getStringsFromValue(value, " ");
+ }
+
+ public static List<String> getStrings(String name, String separator) {
+ List<String> strings = new ArrayList<String>();
+ Properties props = read();
+ if (props.containsKey(name)) {
+ String value = props.getProperty(name);
+ strings = getStringsFromValue(value, separator);
+ }
+ return strings;
+ }
+
+ public static List<String> getStringsFromValue(String value, String separator) {
+ List<String> strings = new ArrayList<String>();
+ try {
+ String[] chunks = value.split(separator);
+ for (String chunk : chunks) {
+ chunk = chunk.trim();
+ if (chunk.length() > 0) {
+ strings.add(chunk);
+ }
+ }
+ } catch (Exception e) {
+ }
+ return strings;
+ }
+
+ private static synchronized Properties read() {
+ File file = new File("gitblit.properties");
+ if (file.exists() && (file.lastModified() > lastread)) {
+ try {
+ properties = new Properties();
+ properties.load(new FileInputStream("gitblit.properties"));
+ lastread = file.lastModified();
+ } catch (FileNotFoundException f) {
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ return properties;
+ }
+}
diff --git a/src/com/gitblit/tests/JGitUtilsTest.java b/src/com/gitblit/tests/JGitUtilsTest.java new file mode 100644 index 00000000..c04ceefd --- /dev/null +++ b/src/com/gitblit/tests/JGitUtilsTest.java @@ -0,0 +1,71 @@ +package com.gitblit.tests;
+
+import java.io.File;
+import java.util.Date;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.storage.file.FileRepository;
+
+import com.gitblit.utils.JGitUtils;
+
+
+public class JGitUtilsTest extends TestCase {
+
+ private File repositoriesFolder = new File("c:/projects/git");
+ private boolean exportAll = true;
+ private boolean readNested = true;
+
+ private List<String> getRepositories() {
+ return JGitUtils.getRepositoryList(repositoriesFolder, exportAll, readNested);
+ }
+
+ private Repository getRepository() throws Exception {
+ return new FileRepository(new File(repositoriesFolder, getRepositories().get(0)) + "/" + Constants.DOT_GIT);
+ }
+
+ public void testFindRepositories() {
+ List<String> list = getRepositories();
+ assertTrue("No repositories found in " + repositoriesFolder, list.size() > 0);
+ }
+
+ public void testOpenRepository() throws Exception {
+ Repository r = getRepository();
+ r.close();
+ assertTrue("Could not find repository!", r != null);
+ }
+
+ public void testLastChangeRepository() throws Exception {
+ Repository r = getRepository();
+ Date date = JGitUtils.getLastChange(r);
+ r.close();
+ assertTrue("Could not get last repository change date!", date != null);
+ }
+
+ public void testRetrieveRevObject() throws Exception {
+ Repository r = getRepository();
+ RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);
+ RevTree tree = commit.getTree();
+ RevObject object = JGitUtils.getRevObject(r, tree, "AUTHORS");
+ r.close();
+ assertTrue("Object is null!", object != null);
+ }
+
+ public void testRetrieveStringContent() throws Exception {
+ Repository r = getRepository();
+ RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);
+ RevTree tree = commit.getTree();
+ RevBlob blob = (RevBlob) JGitUtils.getRevObject(r, tree, "AUTHORS");
+ String content = JGitUtils.getRawContentAsString(r, blob);
+ r.close();
+ assertTrue("Content is null!", content != null);
+ }
+
+}
diff --git a/src/com/gitblit/utils/ByteFormat.java b/src/com/gitblit/utils/ByteFormat.java new file mode 100644 index 00000000..a726368f --- /dev/null +++ b/src/com/gitblit/utils/ByteFormat.java @@ -0,0 +1,82 @@ +/* + * Copyright 2011 Squeal Group. Licensed under the Eclipse Public License, + * Version 1.0 (http://www.eclipse.org/legal/epl-v10.html). + * Initial Developer: Squeal Group + */ +package com.gitblit.utils; + +import java.text.DecimalFormat; +import java.text.FieldPosition; +import java.text.Format; +import java.text.ParsePosition; + +/** + * A formatter for formatting byte sizes. For example, formatting 12345 byes + * results in "12.1 K" and 1234567 results in "1.18 MB". + * + */ +public class ByteFormat extends Format { + + private static final long serialVersionUID = 1L; + + public ByteFormat() { + } + + // Implemented from the Format class + + /** + * Formats a long which represent a number of bytes. + */ + public String format(long bytes) { + return format(Long.valueOf(bytes)); + } + + /** + * Formats a long which represent a number of kilobytes. + */ + public String formatKB(long kilobytes) { + return format(Long.valueOf(kilobytes * 1024)); + } + + /** + * Format the given object (must be a Long). + * + * @param obj + * assumed to be the number of bytes as a Long. + * @param buf + * the StringBuffer to append to. + * @param pos + * @return A formatted string representing the given bytes in more + * human-readable form. + */ + public StringBuffer format(Object obj, StringBuffer buf, FieldPosition pos) { + if (obj instanceof Long) { + long numBytes = ((Long) obj).longValue(); + if (numBytes < 1024) { + DecimalFormat formatter = new DecimalFormat("#,##0"); + buf.append(formatter.format((double) numBytes)).append(" b"); + } else if (numBytes < 1024 * 1024) { + DecimalFormat formatter = new DecimalFormat("#,##0.0"); + buf.append(formatter.format((double) numBytes / 1024.0)).append(" KB"); + } else if (numBytes < 1024 * 1024 * 1024) { + DecimalFormat formatter = new DecimalFormat("#,##0.0"); + buf.append(formatter.format((double) numBytes / (1024.0 * 1024.0))).append(" MB"); + } else { + DecimalFormat formatter = new DecimalFormat("#,##0.0"); + buf.append(formatter.format((double) numBytes / (1024.0 * 1024.0 * 1024.0))).append(" GB"); + } + } + return buf; + } + + /** + * In this implementation, returns null always. + * + * @param source + * @param pos + * @return returns null in this implementation. + */ + public Object parseObject(String source, ParsePosition pos) { + return null; + } +} diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java new file mode 100644 index 00000000..673c9870 --- /dev/null +++ b/src/com/gitblit/utils/JGitUtils.java @@ -0,0 +1,430 @@ +package com.gitblit.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.wicket.models.PathModel;
+import com.gitblit.wicket.models.RefModel;
+
+
+public class JGitUtils {
+
+ /** Prefix for notes refs */
+ public static final String R_NOTES = "refs/notes/";
+
+ /** Standard notes ref */
+ public static final String R_NOTES_COMMITS = R_NOTES + "commits";
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
+
+ public static List<String> getRepositoryList(File repositoriesFolder, boolean exportAll, boolean readNested) {
+ List<String> list = new ArrayList<String>();
+ list.addAll(getNestedRepositories(repositoriesFolder, repositoriesFolder, exportAll, readNested));
+ Collections.sort(list);
+ return list;
+ }
+
+ public static List<String> getNestedRepositories(File repositoriesFolder, File folder, boolean exportAll, boolean readNested) {
+ String basefile = repositoriesFolder.getAbsolutePath();
+ List<String> list = new ArrayList<String>();
+ for (File file : folder.listFiles()) {
+ if (file.isDirectory() && !file.getName().equalsIgnoreCase(Constants.DOT_GIT)) {
+ // if this is a git repository add it to the list
+ File gitFolder = new File(file, Constants.DOT_GIT);
+ boolean isGitRepository = gitFolder.exists() && gitFolder.isDirectory();
+ boolean exportRepository = isGitRepository && (exportAll || new File(gitFolder, "git-daemon-export-ok").exists());
+
+ if (exportRepository) {
+ // determine repository name relative to repositories folder
+ String filename = file.getAbsolutePath();
+ String repo = filename.substring(basefile.length()).replace('\\', '/');
+ if (repo.charAt(0) == '/') {
+ repo = repo.substring(1);
+ }
+ list.add(repo);
+ }
+
+ // look for nested repositories
+ if (readNested) {
+ list.addAll(getNestedRepositories(repositoriesFolder, file, exportAll, readNested));
+ }
+ }
+ }
+ return list;
+ }
+
+ public static Date getLastChange(Repository r) {
+ RevCommit commit = getCommit(r, Constants.HEAD);
+ return getCommitDate(commit);
+ }
+
+ public static RevCommit getCommit(Repository r, String commitId) {
+ RevCommit commit = null;
+ try {
+ ObjectId objectId = r.resolve(commitId);
+ RevWalk walk = new RevWalk(r);
+ RevCommit rev = walk.parseCommit(objectId);
+ commit = rev;
+ walk.dispose();
+ } catch (Throwable t) {
+ LOGGER.error("Failed to determine last change", t);
+ }
+ return commit;
+ }
+
+ public static Map<ObjectId, List<String>> getAllRefs(Repository r) {
+ Map<ObjectId, List<String>> refs = new HashMap<ObjectId, List<String>>();
+ Map<AnyObjectId, Set<Ref>> allRefs = r.getAllRefsByPeeledObjectId();
+ for (AnyObjectId id : allRefs.keySet()) {
+ List<String> list = new ArrayList<String>();
+ for (Ref setRef : allRefs.get(id)) {
+ String name = setRef.getName();
+ list.add(name);
+ }
+ refs.put(id.toObjectId(), list);
+ }
+ return refs;
+ }
+
+ public static Map<ObjectId, List<String>> getRefs(Repository r, String baseRef) {
+ Map<ObjectId, List<String>> refs = new HashMap<ObjectId, List<String>>();
+ Map<AnyObjectId, Set<Ref>> allRefs = r.getAllRefsByPeeledObjectId();
+ for (AnyObjectId id : allRefs.keySet()) {
+ List<String> list = new ArrayList<String>();
+ for (Ref setRef : allRefs.get(id)) {
+ String name = setRef.getName();
+ if (name.startsWith(baseRef)) {
+ list.add(name);
+ }
+ }
+ refs.put(id.toObjectId(), list);
+ }
+ return refs;
+ }
+
+ /**
+ * Lookup an entry stored in a tree, failing if not present.
+ *
+ * @param tree
+ * the tree to search.
+ * @param path
+ * the path to find the entry of.
+ * @return the parsed object entry at this path
+ * @throws Exception
+ */
+ public static RevObject getRevObject(Repository r, final RevTree tree, final String path) {
+ RevObject ro = null;
+ RevWalk rw = new RevWalk(r);
+ TreeWalk tw = new TreeWalk(r);
+ tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
+ try {
+ tw.reset(tree);
+ while (tw.next()) {
+ if (tw.isSubtree() && !path.equals(tw.getPathString())) {
+ tw.enterSubtree();
+ continue;
+ }
+ ObjectId entid = tw.getObjectId(0);
+ FileMode entmode = tw.getFileMode(0);
+ ro = rw.lookupAny(entid, entmode.getObjectType());
+ rw.parseBody(ro);
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Can't find " + path + " in tree " + tree.name(), t);
+ } finally {
+ if (rw != null) {
+ rw.dispose();
+ }
+ }
+ return ro;
+ }
+
+ public static byte[] getRawContent(Repository r, RevBlob blob) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ try {
+ ObjectLoader ldr = r.open(blob.getId(), Constants.OBJ_BLOB);
+ byte[] tmp = new byte[1024];
+ InputStream in = ldr.openStream();
+ int n;
+ while ((n = in.read(tmp)) > 0) {
+ os.write(tmp, 0, n);
+ }
+ in.close();
+ } catch (Throwable t) {
+ LOGGER.error("Failed to read raw content", t);
+ }
+ return os.toByteArray();
+ }
+
+ public static String getRawContentAsString(Repository r, RevBlob blob) {
+ return new String(getRawContent(r, blob));
+ }
+
+ public static String getRawContentAsString(Repository r, RevCommit commit, String blobPath) {
+ RevObject obj = getRevObject(r, commit.getTree(), blobPath);
+ return new String(getRawContent(r, (RevBlob) obj));
+ }
+
+ public static List<PathModel> getFilesInPath(Repository r, String basePath, String commitId) {
+ RevCommit commit = getCommit(r, commitId);
+ return getFilesInPath(r, basePath, commit);
+ }
+
+ public static List<PathModel> getFilesInPath(Repository r, String basePath, RevCommit commit) {
+ List<PathModel> list = new ArrayList<PathModel>();
+ final TreeWalk walk = new TreeWalk(r);
+ try {
+ walk.addTree(commit.getTree());
+ if (basePath != null && basePath.length() > 0) {
+ PathFilter f = PathFilter.create(basePath);
+ walk.setFilter(f);
+ walk.setRecursive(false);
+ boolean foundFolder = false;
+ while (walk.next()) {
+ if (!foundFolder && walk.isSubtree()) {
+ walk.enterSubtree();
+ }
+ if (walk.getPathString().equals(basePath)) {
+ foundFolder = true;
+ continue;
+ }
+ if (foundFolder) {
+ list.add(getPathModel(walk, basePath, commit));
+ }
+ }
+ } else {
+ walk.setRecursive(false);
+ while (walk.next()) {
+ list.add(getPathModel(walk, null, commit));
+ }
+ }
+ } catch (IOException e) {
+ LOGGER.error("Failed to get files for commit " + commit.getName(), e);
+ } finally {
+ walk.release();
+ }
+ Collections.sort(list);
+ return list;
+ }
+
+ public static List<PathModel> getCommitChangedPaths(Repository r, String commitId) {
+ RevCommit commit = getCommit(r, commitId);
+ return getCommitChangedPaths(r, commit);
+ }
+
+ public static List<PathModel> getCommitChangedPaths(Repository r, RevCommit commit) {
+ List<PathModel> list = new ArrayList<PathModel>();
+ final TreeWalk walk = new TreeWalk(r);
+ walk.setRecursive(false);
+ try {
+ walk.addTree(commit.getTree());
+ while (walk.next()) {
+ list.add(getPathModel(walk, null, commit));
+ }
+
+ } catch (IOException e) {
+ LOGGER.error("Failed to get files for commit " + commit.getName(), e);
+ } finally {
+ if (walk != null) {
+ walk.release();
+ }
+ }
+ return list;
+ }
+
+ private static PathModel getPathModel(TreeWalk walk, String basePath, RevCommit commit) {
+ String name;
+ long size = 0;
+ if (basePath == null) {
+ name = walk.getPathString();
+ } else {
+ try {
+ name = walk.getPathString().substring(basePath.length() + 1);
+ } catch (Throwable t) {
+ name = walk.getPathString();
+ }
+ }
+ try {
+ if (!walk.isSubtree()) {
+ size = walk.getObjectReader().getObjectSize(walk.getObjectId(0), Constants.OBJ_BLOB);
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Failed to retrieve blobl size", t);
+ }
+ return new PathModel(name, walk.getPathString(), size, walk.getFileMode(0).getBits(), commit.getName());
+ }
+
+ public static String getPermissionsFromMode(int mode) {
+ if (FileMode.TREE.equals(mode)) {
+ return "drwxr-xr-x";
+ } else if (FileMode.REGULAR_FILE.equals(mode)) {
+ return "-rw-r--r--";
+ } else if (FileMode.EXECUTABLE_FILE.equals(mode)) {
+ return "-rwxr-xr-x";
+ } else if (FileMode.SYMLINK.equals(mode)) {
+ // FIXME symlink permissions
+ return "symlink";
+ } else if (FileMode.GITLINK.equals(mode)) {
+ // FIXME gitlink permissions
+ return "gitlink";
+ } else if (FileMode.MISSING.equals(mode)) {
+ // FIXME missing permissions
+ return "missing";
+ }
+ return "" + mode;
+ }
+
+ public static boolean isTreeFromMode(int mode) {
+ return FileMode.TREE.equals(mode);
+ }
+
+
+ public static List<RevCommit> getRevLog(Repository r, int maxCount) {
+ List<RevCommit> list = new ArrayList<RevCommit>();
+ try {
+ Git git = new Git(r);
+ Iterable<RevCommit> revlog = git.log().call();
+ for (RevCommit rev : revlog) {
+ list.add(rev);
+ if (maxCount > 0 && list.size() == maxCount) {
+ break;
+ }
+ }
+ } catch (Throwable t) {
+ LOGGER.error("Failed to determine last change", t);
+ }
+ return list;
+ }
+
+ public static List<RefModel> getTags(Repository r, int maxCount) {
+ return getRefs(r, Constants.R_TAGS, maxCount);
+ }
+
+ public static List<RefModel> getHeads(Repository r, int maxCount) {
+ return getRefs(r, Constants.R_HEADS, maxCount);
+ }
+
+ public static List<RefModel> getRefs(Repository r, String refs, int maxCount) {
+ List<RefModel> list = new ArrayList<RefModel>();
+ try {
+ Map<String, Ref> map = r.getRefDatabase().getRefs(refs);
+ for (String name : map.keySet()) {
+ Ref ref = map.get(name);
+ RevCommit commit = getCommit(r, ref.getObjectId().getName());
+ list.add(new RefModel(name, ref, commit));
+ }
+ Collections.sort(list);
+ Collections.reverse(list);
+ if (maxCount > 0 && list.size() > maxCount) {
+ list = list.subList(0, maxCount);
+ }
+ } catch (IOException e) {
+ LOGGER.error("Failed to retrieve " + refs, e);
+ }
+ return list;
+ }
+
+ public static Ref getRef(Repository r, String id) {
+ try {
+ Map<String, Ref> map = r.getRefDatabase().getRefs(id);
+ for (String name : map.keySet()) {
+ return map.get(name);
+ }
+ } catch (IOException e) {
+ LOGGER.error("Failed to retrieve ref " + id, e);
+ }
+ return null;
+ }
+
+ public static Date getCommitDate(RevCommit commit) {
+ return new Date(commit.getCommitTime() * 1000l);
+ }
+
+ public static String getDisplayName(PersonIdent person) {
+ final StringBuilder r = new StringBuilder();
+ r.append(person.getName());
+ r.append(" <");
+ r.append(person.getEmailAddress());
+ r.append(">");
+ return r.toString();
+ }
+
+ public static String getRepositoryDescription(Repository r) {
+ File dir = r.getDirectory();
+ if (dir.exists()) {
+ File description = new File(dir, "description");
+ if (description.exists() && description.length() > 0) {
+ RandomAccessFile raf = null;
+ try {
+ raf = new RandomAccessFile(description, "r");
+ byte[] buffer = new byte[(int) description.length()];
+ raf.readFully(buffer);
+ return new String(buffer);
+ } catch (Throwable t) {
+ } finally {
+ try {
+ raf.close();
+ } catch (Throwable t) {
+ }
+ }
+ }
+ }
+ return "";
+ }
+
+ public static String getRepositoryOwner(Repository r) {
+ StoredConfig c = readConfig(r);
+ if (c == null) {
+ return "";
+ }
+ String o = c.getString("gitweb", null, "owner");
+ return o == null ? "" : o;
+ }
+
+ private static StoredConfig readConfig(Repository r) {
+ StoredConfig c = r.getConfig();
+ if (c != null) {
+ try {
+ c.load();
+ } catch (ConfigInvalidException cex) {
+ LOGGER.error("Repository configuration is invalid!", cex);
+ } catch (IOException cex) {
+ LOGGER.error("Could not open repository configuration!", cex);
+ }
+ return c;
+ }
+ return null;
+ }
+}
diff --git a/src/com/gitblit/utils/Utils.java b/src/com/gitblit/utils/Utils.java new file mode 100644 index 00000000..bef41b29 --- /dev/null +++ b/src/com/gitblit/utils/Utils.java @@ -0,0 +1,119 @@ +package com.gitblit.utils;
+
+import java.util.Date;
+
+public class Utils {
+ private final static long min = 1000 * 60l;
+
+ private final static long halfhour = min * 30l;
+
+ private final static long onehour = halfhour * 2;
+
+ private final static long oneday = onehour * 24l;
+
+ @SuppressWarnings("deprecation")
+ public static boolean isToday(Date date) {
+ Date now = new Date();
+ return now.getDate() == date.getDate() && now.getMonth() == date.getMonth() && now.getYear() == date.getYear();
+ }
+
+ @SuppressWarnings("deprecation")
+ public static boolean isYesterday(Date date) {
+ Date now = new Date();
+ return now.getDate() == (date.getDate() + 1) && now.getMonth() == date.getMonth() && now.getYear() == date.getYear();
+ }
+
+ public static int minutesAgo(Date date, long endTime, boolean roundup) {
+ long diff = endTime - date.getTime();
+ int mins = (int) (diff / min);
+ if (roundup && (diff % min) >= 30)
+ mins++;
+ return mins;
+ }
+
+ public static int minutesAgo(Date date, boolean roundup) {
+ return minutesAgo(date, System.currentTimeMillis(), roundup);
+ }
+
+ public static int hoursAgo(Date date, boolean roundup) {
+ long diff = System.currentTimeMillis() - date.getTime();
+ int hours = (int) (diff / onehour);
+ if (roundup && (diff % onehour) >= halfhour)
+ hours++;
+ return hours;
+ }
+
+ public static int daysAgo(Date date, boolean roundup) {
+ long diff = System.currentTimeMillis() - date.getTime();
+ int days = (int) (diff / oneday);
+ if (roundup && (diff % oneday) > 0)
+ days++;
+ return days;
+ }
+
+ public static String timeAgo(Date date) {
+ return timeAgo(date, false);
+ }
+
+ public static String timeAgoCss(Date date) {
+ return timeAgo(date, true);
+ }
+
+ private static String timeAgo(Date date, boolean css) {
+ String ago = null;
+ if (isToday(date) || isYesterday(date)) {
+ int mins = minutesAgo(date, true);
+ if (mins > 120) {
+ if (css) {
+ return "age1";
+ }
+ int hours = hoursAgo(date, true);
+ if (hours > 23) {
+ ago = "yesterday";
+ } else {
+ ago = hours + " hour" + (hours > 1 ? "s" : "") + " ago";
+ }
+ } else {
+ if (css) {
+ return "age0";
+ }
+ ago = mins + " min" + (mins > 1 ? "s" : "") + " ago";
+ }
+ } else {
+ if (css) {
+ return "age2";
+ }
+ int days = daysAgo(date, true);
+ if (days < 365) {
+ if (days <= 30) {
+ ago = days + " day" + (days > 1 ? "s" : "") + " ago";
+ } else if (days <= 90) {
+ int weeks = days / 7;
+ if (weeks == 12)
+ ago = "3 months ago";
+ else
+ ago = weeks + " weeks ago";
+ } else if (days > 90) {
+ int months = days / 30;
+ int weeks = (days % 30) / 7;
+ if (weeks >= 2)
+ months++;
+ ago = months + " month" + (months > 1 ? "s" : "") + " ago";
+ } else
+ ago = days + " day" + (days > 1 ? "s" : "") + " ago";
+ } else if (days == 365) {
+ ago = "1 year ago";
+ } else {
+ int yr = days / 365;
+ days = days % 365;
+ int months = (yr * 12) + (days / 30);
+ if (months > 23) {
+ ago = yr + " years ago";
+ } else {
+ ago = months + " months ago";
+ }
+ }
+ }
+ return ago;
+ }
+}
diff --git a/src/com/gitblit/wicket/BasePage.java b/src/com/gitblit/wicket/BasePage.java new file mode 100644 index 00000000..5d8176a2 --- /dev/null +++ b/src/com/gitblit/wicket/BasePage.java @@ -0,0 +1,69 @@ +package com.gitblit.wicket;
+
+import java.util.Date;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.utils.Utils;
+
+
+public abstract class BasePage extends WebPage {
+
+ Logger logger = LoggerFactory.getLogger(BasePage.class);
+
+ public BasePage() {
+ super();
+ }
+
+ public BasePage(PageParameters params) {
+ super(params);
+ }
+
+ protected Label createAuthorLabel(String wicketId, String author) {
+ Label label = new Label(wicketId, author);
+ WicketUtils.setHtmlTitle(label, author);
+ return label;
+ }
+
+ protected Label createDateLabel(String wicketId, Date date) {
+ Label label = new Label(wicketId, GitBlitWebSession.get().formatDate(date));
+ WicketUtils.setCssClass(label, Utils.timeAgoCss(date));
+ WicketUtils.setHtmlTitle(label, Utils.timeAgo(date));
+ return label;
+ }
+
+ protected Label createShortlogDateLabel(String wicketId, Date date) {
+ String dateString = GitBlitWebSession.get().formatDate(date);
+ String title = Utils.timeAgo(date);
+ if ((System.currentTimeMillis() - date.getTime()) < 10 * 24 * 60 * 60 * 1000l) {
+ dateString = title;
+ title = GitBlitWebSession.get().formatDate(date);
+ }
+ Label label = new Label(wicketId, dateString);
+ WicketUtils.setCssClass(label, Utils.timeAgoCss(date));
+ WicketUtils.setHtmlTitle(label, title);
+ return label;
+ }
+
+ protected void setAlternatingBackground(Component c, int i) {
+ String clazz = i % 2 == 0 ? "dark" : "light";
+ WicketUtils.setCssClass(c, clazz);
+ }
+
+ protected String trimShortLog(String string) {
+ if (string.length() > 60) {
+ return string.substring(0, 60) + "...";
+ }
+ return string;
+ }
+
+ public void error(String message, Throwable t) {
+ super.error(message);
+ logger.error(message, t);
+ }
+}
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.java b/src/com/gitblit/wicket/GitBlitWebApp.java new file mode 100644 index 00000000..2a245fa8 --- /dev/null +++ b/src/com/gitblit/wicket/GitBlitWebApp.java @@ -0,0 +1,143 @@ +package com.gitblit.wicket;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Page;
+import org.apache.wicket.Request;
+import org.apache.wicket.Response;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.protocol.http.request.urlcompressing.UrlCompressingWebRequestProcessor;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.IRequestCycleProcessor;
+import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.http.server.resolver.FileResolver;
+import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
+import org.eclipse.jgit.lib.Repository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.GitBlitServer;
+import com.gitblit.StoredSettings;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.models.RepositoryModel;
+import com.gitblit.wicket.pages.BlobPage;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.HeadsPage;
+import com.gitblit.wicket.pages.LogPage;
+import com.gitblit.wicket.pages.RepositoriesPage;
+import com.gitblit.wicket.pages.ShortLogPage;
+import com.gitblit.wicket.pages.SummaryPage;
+import com.gitblit.wicket.pages.TagPage;
+import com.gitblit.wicket.pages.TagsPage;
+import com.gitblit.wicket.pages.TreePage;
+
+
+public class GitBlitWebApp extends WebApplication {
+
+ public static int PAGING_ITEM_COUNT = 50;
+
+ Logger logger = LoggerFactory.getLogger(GitBlitWebApp.class);
+
+ FileResolver repositoryResolver;
+
+ private File repositories;
+
+ private boolean exportAll;
+
+ @Override
+ public void init() {
+ super.init();
+
+ // Grab Browser info (like timezone, etc)
+ getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
+
+ // setup the url paths
+ mount(new MixedParamUrlCodingStrategy("/summary", SummaryPage.class, new String[] { "p" }));
+ mount(new MixedParamUrlCodingStrategy("/shortlog", ShortLogPage.class, new String[] { "p", "h" }));
+ mount(new MixedParamUrlCodingStrategy("/log", LogPage.class, new String[] { "p", "h" }));
+ mount(new MixedParamUrlCodingStrategy("/tags", TagsPage.class, new String[] { "p" }));
+ mount(new MixedParamUrlCodingStrategy("/heads", HeadsPage.class, new String[] { "p" }));
+ mount(new MixedParamUrlCodingStrategy("/commit", CommitPage.class, new String[] { "p", "h" }));
+ mount(new MixedParamUrlCodingStrategy("/tag", TagPage.class, new String[] { "p", "h" }));
+ mount(new MixedParamUrlCodingStrategy("/tree", TreePage.class, new String[] { "p", "h", "f" }));
+ mount(new MixedParamUrlCodingStrategy("/blob", BlobPage.class, new String[] { "p", "h", "f" }));
+
+ repositories = new File(StoredSettings.getString("repositoriesFolder", "repos"));
+ exportAll = StoredSettings.getBoolean("exportAll", true);
+ repositoryResolver = new FileResolver(repositories, exportAll);
+ }
+
+ @Override
+ public Class<? extends Page> getHomePage() {
+ return RepositoriesPage.class;
+ }
+
+ @Override
+ public final Session newSession(Request request, Response response) {
+ return new GitBlitWebSession(request);
+ }
+
+ @Override
+ protected final IRequestCycleProcessor newRequestCycleProcessor() {
+ return new UrlCompressingWebRequestProcessor();
+ }
+
+ @Override
+ public final String getConfigurationType() {
+ if (GitBlitServer.isDebugMode())
+ return Application.DEVELOPMENT;
+ return Application.DEPLOYMENT;
+ }
+
+ public List<String> getRepositoryList() {
+ return JGitUtils.getRepositoryList(repositories, exportAll, StoredSettings.getBoolean("nestedRepositories", true));
+ }
+
+ public List<RepositoryModel> getRepositories(Request request) {
+ List<String> list = getRepositoryList();
+ ServletWebRequest servletWebRequest = (ServletWebRequest) request;
+ HttpServletRequest req = servletWebRequest.getHttpServletRequest();
+
+ List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();
+ for (String repo : list) {
+ Repository r = getRepository(req, repo);
+ String description = JGitUtils.getRepositoryDescription(r);
+ String owner = JGitUtils.getRepositoryOwner(r);
+ Date lastchange = JGitUtils.getLastChange(r);
+ r.close();
+ repositories.add(new RepositoryModel(repo, description, owner, lastchange));
+ }
+ return repositories;
+ }
+
+ public Repository getRepository(HttpServletRequest req, String repositoryName) {
+ Repository r = null;
+ try {
+ r = repositoryResolver.open(req, repositoryName);
+ } catch (RepositoryNotFoundException e) {
+ r = null;
+ logger.error("Failed to find repository " + repositoryName);
+ e.printStackTrace();
+ } catch (ServiceNotEnabledException e) {
+ r = null;
+ e.printStackTrace();
+ }
+ return r;
+ }
+
+ public String getCloneUrl(String repositoryName) {
+ return StoredSettings.getString("cloneUrl", "https://localhost/git/") + repositoryName;
+ }
+
+ public static GitBlitWebApp get() {
+ return (GitBlitWebApp) WebApplication.get();
+ }
+}
diff --git a/src/com/gitblit/wicket/GitBlitWebSession.java b/src/com/gitblit/wicket/GitBlitWebSession.java new file mode 100644 index 00000000..1eccb702 --- /dev/null +++ b/src/com/gitblit/wicket/GitBlitWebSession.java @@ -0,0 +1,74 @@ +package com.gitblit.wicket;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.wicket.Request;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebSession;
+import org.apache.wicket.protocol.http.request.WebClientInfo;
+
+import com.gitblit.StoredSettings;
+
+
+public final class GitBlitWebSession extends WebSession {
+
+ private static final long serialVersionUID = 1L;
+
+ protected TimeZone timezone = null;
+
+ public GitBlitWebSession(Request request) {
+ super(request);
+ }
+
+ public void invalidate() {
+ super.invalidate();
+ }
+
+ public TimeZone getTimezone() {
+ if (timezone == null) {
+ timezone = ((WebClientInfo) getClientInfo()).getProperties().getTimeZone();
+ }
+ // use server timezone if we can't determine the client timezone
+ if (timezone == null) {
+ timezone = TimeZone.getDefault();
+ }
+ return timezone;
+ }
+
+ public String formatTime(Date date) {
+ DateFormat df = new SimpleDateFormat(StoredSettings.getString("timestampFormat", "h:mm a"));
+ df.setTimeZone(getTimezone());
+ return df.format(date);
+ }
+
+ public String formatDate(Date date) {
+ DateFormat df = new SimpleDateFormat(StoredSettings.getString("datestampShortFormat", "MM/dd/yy"));
+ df.setTimeZone(getTimezone());
+ return df.format(date);
+ }
+
+ public String formatDateLong(Date date) {
+ DateFormat df = new SimpleDateFormat(StoredSettings.getString("datestampLongFormat", "EEEE, MMMM d, yyyy"));
+ df.setTimeZone(getTimezone());
+ return df.format(date);
+ }
+
+ public String formatDateTime(Date date) {
+ DateFormat df = new SimpleDateFormat(StoredSettings.getString("datetimestampShortFormat", "MM/dd/yy h:mm a"));
+ df.setTimeZone(getTimezone());
+ return df.format(date);
+ }
+
+ public String formatDateTimeLong(Date date) {
+ DateFormat df = new SimpleDateFormat(StoredSettings.getString("datetimestampLongFormat", "EEEE, MMMM d, yyyy h:mm a"));
+ df.setTimeZone(getTimezone());
+ return df.format(date);
+ }
+
+ public static GitBlitWebSession get() {
+ return (GitBlitWebSession) Session.get();
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/LinkPanel.html b/src/com/gitblit/wicket/LinkPanel.html new file mode 100644 index 00000000..7abf14ce --- /dev/null +++ b/src/com/gitblit/wicket/LinkPanel.html @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+<a href="#" wicket:id="link"><span wicket:id="label">link</span></a>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/LinkPanel.java b/src/com/gitblit/wicket/LinkPanel.java new file mode 100644 index 00000000..afa2647b --- /dev/null +++ b/src/com/gitblit/wicket/LinkPanel.java @@ -0,0 +1,44 @@ +package com.gitblit.wicket;
+
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+public class LinkPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ private IModel<String> labelModel = new Model<String>();
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public LinkPanel(String wicketId, final String linkCssClass, String label, Class<? extends WebPage> clazz, PageParameters parameters) {
+ super(wicketId);
+ Link<?> link = null;
+ if (parameters == null) {
+ link = new BookmarkablePageLink("link", clazz);
+ } else {
+ link = new BookmarkablePageLink("link", clazz, parameters);
+ }
+ if (linkCssClass != null) {
+ link.add(new AttributeModifier("class", true, new AbstractReadOnlyModel<String>() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getObject() {
+ return linkCssClass;
+ }
+ }));
+ }
+ labelModel.setObject(label);
+ link.add(new Label("label", labelModel));
+ add(link);
+ }
+
+}
diff --git a/src/com/gitblit/wicket/RepositoryPage.java b/src/com/gitblit/wicket/RepositoryPage.java new file mode 100644 index 00000000..4371052b --- /dev/null +++ b/src/com/gitblit/wicket/RepositoryPage.java @@ -0,0 +1,118 @@ +package com.gitblit.wicket;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.StoredSettings;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.pages.RepositoriesPage;
+import com.gitblit.wicket.panels.PageFooter;
+import com.gitblit.wicket.panels.PageHeader;
+import com.gitblit.wicket.panels.PageLinksPanel;
+import com.gitblit.wicket.panels.RefsPanel;
+
+
+public abstract class RepositoryPage extends BasePage {
+
+ protected final String repositoryName;
+ protected final String commitId;
+ protected String description;
+
+ public RepositoryPage(PageParameters params, String pageName) {
+ super(params);
+ if (!params.containsKey("p")) {
+ error("Repository not specified!");
+ redirectToInterceptPage(new RepositoriesPage());
+ }
+ repositoryName = params.getString("p", "");
+ commitId = params.getString("h", "");
+
+ add(new PageHeader("pageHeader", repositoryName, "/ " + pageName));
+ add(new PageLinksPanel("pageLinks", repositoryName, pageName));
+ setStatelessHint(true);
+ }
+
+ protected Repository getRepository() {
+ ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
+ HttpServletRequest req = servletWebRequest.getHttpServletRequest();
+ req.getServerName();
+
+ Repository r = GitBlitWebApp.get().getRepository(req, repositoryName);
+ if (r == null) {
+ error("Can not load repository " + repositoryName);
+ redirectToInterceptPage(new RepositoriesPage());
+ return null;
+ }
+ description = JGitUtils.getRepositoryDescription(r);
+ return r;
+ }
+
+ protected void addRefs(Repository r, RevCommit c) {
+ add(new RefsPanel("refsPanel", r, c));
+ }
+
+ protected void addFullText(String wicketId, String text, boolean substituteRegex) {
+ String html = WicketUtils.breakLines(text);
+ if (substituteRegex) {
+ Map<String, String> map = new HashMap<String, String>();
+ // global regex keys
+ for (String key : StoredSettings.getAllKeys("regex.global")) {
+ String subKey = key.substring(key.lastIndexOf('.') + 1);
+ map.put(subKey, StoredSettings.getString(key, ""));
+ }
+
+ // repository-specific regex keys
+ List<String> keys = StoredSettings.getAllKeys("regex." + repositoryName.toLowerCase());
+ for (String key : keys) {
+ String subKey = key.substring(key.lastIndexOf('.') + 1);
+ map.put(subKey, StoredSettings.getString(key, ""));
+ }
+
+ for (String key : map.keySet()) {
+ String definition = map.get(key).trim();
+ String [] chunks = definition.split("!!!");
+ if (chunks.length == 2) {
+ html = html.replaceAll(chunks[0], chunks[1]);
+ } else {
+ logger.warn(key + " improperly formatted. Use !!! to separate match from replacement: " + definition);
+ }
+ }
+ }
+ add(new Label(wicketId, html).setEscapeModelStrings(false));
+ }
+
+ protected void addFooter() {
+ add(new PageFooter("pageFooter", description));
+ }
+
+ protected PageParameters newRepositoryParameter() {
+ return new PageParameters("p=" + repositoryName);
+ }
+
+ protected PageParameters newCommitParameter() {
+ return newCommitParameter(commitId);
+ }
+
+ protected PageParameters newCommitParameter(String commitId) {
+ if (commitId == null || commitId.trim().length() == 0) {
+ return newRepositoryParameter();
+ }
+ return new PageParameters("p=" + repositoryName + ",h=" + commitId);
+ }
+
+ protected PageParameters newPathParameter(String path) {
+ if (path == null || path.trim().length() == 0) {
+ return newCommitParameter();
+ }
+ return new PageParameters("p=" + repositoryName + ",h=" + commitId + ",f=" + path);
+ }
+}
diff --git a/src/com/gitblit/wicket/SecuredPage.java b/src/com/gitblit/wicket/SecuredPage.java new file mode 100644 index 00000000..c3153a67 --- /dev/null +++ b/src/com/gitblit/wicket/SecuredPage.java @@ -0,0 +1,11 @@ +package com.gitblit.wicket;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SecuredPage {
+}
diff --git a/src/com/gitblit/wicket/WicketUtils.java b/src/com/gitblit/wicket/WicketUtils.java new file mode 100644 index 00000000..1d85a80b --- /dev/null +++ b/src/com/gitblit/wicket/WicketUtils.java @@ -0,0 +1,35 @@ +package com.gitblit.wicket;
+
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+
+public class WicketUtils {
+
+ public static void setCssClass(Component container, String value) {
+ container.add(newAttributeModifier("class", value));
+ }
+
+ public static void setCssStyle(Component container, String value) {
+ container.add(newAttributeModifier("style", value));
+ }
+
+ public static void setHtmlTitle(Component container, String value) {
+ container.add(newAttributeModifier("title", value));
+ }
+
+ private static AttributeModifier newAttributeModifier(String attrib, final String value) {
+ return new AttributeModifier(attrib, true, new AbstractReadOnlyModel<String>() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getObject() {
+ return value;
+ }
+ });
+ }
+
+ public static String breakLines(String string) {
+ return string.replace("\r", "<br/>").replace("\n", "<br/>");
+ }
+}
diff --git a/src/com/gitblit/wicket/models/PathModel.java b/src/com/gitblit/wicket/models/PathModel.java new file mode 100644 index 00000000..3fa0f633 --- /dev/null +++ b/src/com/gitblit/wicket/models/PathModel.java @@ -0,0 +1,45 @@ +package com.gitblit.wicket.models;
+
+import java.io.Serializable;
+
+import com.gitblit.utils.JGitUtils;
+
+
+public class PathModel implements Serializable, Comparable<PathModel> {
+
+ private static final long serialVersionUID = 1L;
+
+ public final String name;
+ public final String path;
+ public final long size;
+ public final int mode;
+ public final String commitId;
+ public boolean isParentPath;
+
+ public PathModel(String name, String path, long size, int mode, String commitId) {
+ this.name = name;
+ this.path = path;
+ this.size = size;
+ this.mode = mode;
+ this.commitId = commitId;
+ }
+
+ public boolean isTree() {
+ return JGitUtils.isTreeFromMode(mode);
+ }
+
+ public static PathModel getParentPath(String basePath, String commitId) {
+ String parentPath = null;
+ if (basePath.lastIndexOf('/') > -1) {
+ parentPath = basePath.substring(0, basePath.lastIndexOf('/'));
+ }
+ PathModel model = new PathModel("..", parentPath, 0, 0040000, commitId);
+ model.isParentPath = true;
+ return model;
+ }
+
+ @Override
+ public int compareTo(PathModel o) {
+ return path.compareTo(o.path);
+ }
+}
diff --git a/src/com/gitblit/wicket/models/RefModel.java b/src/com/gitblit/wicket/models/RefModel.java new file mode 100644 index 00000000..e76b489d --- /dev/null +++ b/src/com/gitblit/wicket/models/RefModel.java @@ -0,0 +1,54 @@ +package com.gitblit.wicket.models;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+
+
+public class RefModel implements Serializable, Comparable<RefModel> {
+
+ private static final long serialVersionUID = 1L;
+ final String displayName;
+ transient Ref ref;
+ final RevCommit commit;
+
+ public RefModel(String displayName, Ref ref, RevCommit commit) {
+ this.displayName = displayName;
+ this.ref = ref;
+ this.commit = commit;
+ }
+
+ public Date getDate() {
+ return JGitUtils.getCommitDate(commit);
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public String getName() {
+ return ref.getName();
+ }
+
+ public ObjectId getCommitId() {
+ return commit.getId();
+ }
+
+ public String getShortLog() {
+ return commit.getShortMessage();
+ }
+
+ public ObjectId getObjectId() {
+ return ref.getObjectId();
+ }
+
+ @Override
+ public int compareTo(RefModel o) {
+ return getDate().compareTo(o.getDate());
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/models/RepositoryModel.java b/src/com/gitblit/wicket/models/RepositoryModel.java new file mode 100644 index 00000000..7ce98e0c --- /dev/null +++ b/src/com/gitblit/wicket/models/RepositoryModel.java @@ -0,0 +1,20 @@ +package com.gitblit.wicket.models;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class RepositoryModel implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ public final String name;
+ public final String description;
+ public final String owner;
+ public final Date lastChange;
+
+ public RepositoryModel(String name, String description, String owner, Date lastchange) {
+ this.name = name;
+ this.description = description;
+ this.owner = owner;
+ this.lastChange = lastchange;
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/BlobPage.html b/src/com/gitblit/wicket/pages/BlobPage.html new file mode 100644 index 00000000..6d04e180 --- /dev/null +++ b/src/com/gitblit/wicket/pages/BlobPage.html @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head>
+ <link href="prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="prettify/prettify.js"></script>
+</head>
+<body onload="prettyPrint()">
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- blob nav links -->
+ <div class="page_nav2">
+ <span wicket:id="historyLink"></span> | <span wicket:id="rawLink"></span> | <span wicket:id="headLink"></span>
+ </div>
+
+ <!-- shortlog header -->
+ <div class="header" wicket:id="shortlog"></div>
+
+ <!-- breadcrumbs -->
+ <div wicket:id="breadcrumbs"></div>
+
+ <!-- blob content -->
+ <pre wicket:id="blobText"></pre>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/BlobPage.java b/src/com/gitblit/wicket/pages/BlobPage.java new file mode 100644 index 00000000..979bb261 --- /dev/null +++ b/src/com/gitblit/wicket/pages/BlobPage.java @@ -0,0 +1,94 @@ +package com.gitblit.wicket.pages;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.StoredSettings;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.panels.PathBreadcrumbsPanel;
+
+
+public class BlobPage extends RepositoryPage {
+
+ public BlobPage(PageParameters params) {
+ super(params, "blob");
+
+ final String blobPath = params.getString("f", null);
+
+ Repository r = getRepository();
+ RevCommit commit = JGitUtils.getCommit(r, commitId);
+
+ // blob page links
+ add(new Label("historyLink", "history"));
+ add(new Label("rawLink", "raw"));
+ add(new Label("headLink", "HEAD"));
+
+ add(new LinkPanel("shortlog", "title", commit.getShortMessage(), CommitPage.class, newCommitParameter()));
+
+ add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, blobPath, commitId));
+ String extension = null;
+ if (blobPath.lastIndexOf('.') > -1) {
+ extension = blobPath.substring(blobPath.lastIndexOf('.') + 1);
+ }
+
+ // Map the extensions to types
+ Map<String, Integer> map = new HashMap<String, Integer>();
+ for (String ext : StoredSettings.getStrings("prettyPrintExtensions")) {
+ map.put(ext.toLowerCase(), 1);
+ }
+ for (String ext : StoredSettings.getStrings("imageExtensions")) {
+ map.put(ext.toLowerCase(), 2);
+ }
+ for (String ext : StoredSettings.getStrings("binaryExtensions")) {
+ map.put(ext.toLowerCase(), 3);
+ }
+
+ if (extension != null) {
+ int type = 0;
+ if (map.containsKey(extension)) {
+ type = map.get(extension);
+ }
+ Component c = null;
+ switch (type) {
+ case 1:
+ // PrettyPrint blob text
+ c = new Label("blobText", JGitUtils.getRawContentAsString(r, commit, blobPath));
+ WicketUtils.setCssClass(c, "prettyprint");
+ break;
+ case 2:
+ // TODO image blobs
+ c = new Label("blobText", "Image File");
+ break;
+ case 3:
+ // TODO binary blobs
+ c = new Label("blobText", "Binary File");
+ break;
+ default:
+ // plain text
+ c = new Label("blobText", JGitUtils.getRawContentAsString(r, commit, blobPath));
+ WicketUtils.setCssClass(c, "plainprint");
+ }
+ add(c);
+ } else {
+ // plain text
+ Label blobLabel = new Label("blobText", JGitUtils.getRawContentAsString(r, commit, blobPath));
+ WicketUtils.setCssClass(blobLabel, "plainprint");
+ add(blobLabel);
+ }
+
+ // close repository
+ r.close();
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/CommitPage.html b/src/com/gitblit/wicket/pages/CommitPage.html new file mode 100644 index 00000000..a493e047 --- /dev/null +++ b/src/com/gitblit/wicket/pages/CommitPage.html @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- commit nav links -->
+ <div class="page_nav2">
+ (parent: <span wicket:id="parentLink"></span>) | <span wicket:id="patchLink"></span>
+ </div>
+
+ <!-- shortlog header -->
+ <div class="header" wicket:id="shortlog"></div>
+
+ <!-- Refs -->
+ <div wicket:id="refsPanel"></div>
+
+ <!-- commit info -->
+ <div class="title_text">
+ <table class="object_header">
+ <tr><td>author</td><td><span wicket:id="commitAuthor">Message goes here</span></td></tr>
+ <tr><td></td><td><span wicket:id="commitAuthorDate">Message goes here</span></td></tr>
+ <tr><td>committer</td><td><span wicket:id="commitCommitter">Message goes here</span></td></tr>
+ <tr><td></td><td><span wicket:id="commitCommitterDate">Message goes here</span></td></tr>
+ <tr><td>commit</td><td class="sha1"><span wicket:id="commitId">Message goes here</span></td></tr>
+ <tr><td>tree</td><td class="sha1"><span wicket:id="commitTree">Message goes here</span></td></tr>
+ <tr><td>parent</td><td class="sha1"><span wicket:id="commitParents">
+ <div wicket:id="commitParent">Message goes here</div></span></td></tr>
+ </table>
+ </div>
+
+ <!-- full message -->
+ <div class="page_body" wicket:id="fullMessage"></div>
+
+ <!-- changed paths -->
+ <div class="list_head"></div>
+ <table class="diff_tree">
+ <tr wicket:id="changedPath">
+ <td class="path"><span wicket:id="pathName"></span></td>
+ <td></td>
+ <td><span wicket:id="pathLinks"></span></td>
+ </tr>
+ </table>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/CommitPage.java b/src/com/gitblit/wicket/pages/CommitPage.java new file mode 100644 index 00000000..ad1fce06 --- /dev/null +++ b/src/com/gitblit/wicket/pages/CommitPage.java @@ -0,0 +1,106 @@ +package com.gitblit.wicket.pages;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.models.PathModel;
+import com.gitblit.wicket.panels.PathLinksPanel;
+
+
+public class CommitPage extends RepositoryPage {
+
+ public CommitPage(PageParameters params) {
+ super(params, "commit");
+
+ final String commitId = params.getString("h", "");
+
+ Repository r = getRepository();
+ RevCommit c = JGitUtils.getCommit(r, commitId);
+
+ List<String> parents = new ArrayList<String>();
+ if (c.getParentCount() > 0) {
+ for (RevCommit parent : c.getParents()) {
+ parents.add(parent.name());
+ }
+ }
+
+ // commit page links
+ if (parents.size() == 0) {
+ add(new Label("parentLink", "none"));
+ } else {
+ add(new LinkPanel("parentLink", null, parents.get(0).substring(0, 8), CommitPage.class, newCommitParameter(parents.get(0))));
+ }
+ add(new Label("patchLink", "patch"));
+
+ add(new LinkPanel("shortlog", "title", c.getShortMessage(), ShortLogPage.class, newRepositoryParameter()));
+
+ addRefs(r, c);
+
+ add(new Label("commitAuthor", JGitUtils.getDisplayName(c.getAuthorIdent())));
+ String authorDate = GitBlitWebSession.get().formatDateTimeLong(c.getAuthorIdent().getWhen());
+ add(new Label("commitAuthorDate", authorDate));
+
+ add(new Label("commitCommitter", JGitUtils.getDisplayName(c.getCommitterIdent())));
+ String comitterDate = GitBlitWebSession.get().formatDateTimeLong(c.getCommitterIdent().getWhen());
+ add(new Label("commitCommitterDate", comitterDate));
+
+ add(new Label("commitId", c.getName()));
+
+ add(new LinkPanel("commitTree", "list", c.getTree().getName(), TreePage.class, newCommitParameter()));
+
+ // Parent Commits
+ ListDataProvider<String> parentsDp = new ListDataProvider<String>(parents);
+ DataView<String> parentsView = new DataView<String>("commitParents", parentsDp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<String> item) {
+ String entry = item.getModelObject();
+ item.add(new LinkPanel("commitParent", "list", entry, CommitPage.class, newCommitParameter(entry)));
+ }
+ };
+ add(parentsView);
+
+ addFullText("fullMessage", c.getFullMessage(), true);
+
+ // changed paths list
+ List<PathModel> paths = JGitUtils.getCommitChangedPaths(r, c);
+ ListDataProvider<PathModel> pathsDp = new ListDataProvider<PathModel>(paths);
+ DataView<PathModel> pathsView = new DataView<PathModel>("changedPath", pathsDp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<PathModel> item) {
+ final PathModel entry = item.getModelObject();
+ if (entry.isTree()) {
+ item.add(new LinkPanel("pathName", null, entry.path, TreePage.class, newPathParameter(entry.path)));
+ } else {
+ item.add(new LinkPanel("pathName", "list", entry.path, BlobPage.class, newPathParameter(entry.path)));
+ }
+ item.add(new PathLinksPanel("pathLinks", repositoryName, entry));
+ String clazz = counter % 2 == 0 ? "dark" : "light";
+ WicketUtils.setCssClass(item, clazz);
+ counter++;
+ }
+ };
+ add(pathsView);
+
+ // close repository
+ r.close();
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/HeadsPage.html b/src/com/gitblit/wicket/pages/HeadsPage.html new file mode 100644 index 00000000..cd914363 --- /dev/null +++ b/src/com/gitblit/wicket/pages/HeadsPage.html @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- shortlog -->
+ <div class="header" wicket:id="summary"></div>
+
+ <table class="heads">
+ <tbody>
+ <tr wicket:id="head">
+ <td><i><span wicket:id="headDate"></span></i></td>
+ <td><div wicket:id="headName"></div></td>
+ <td></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/HeadsPage.java b/src/com/gitblit/wicket/pages/HeadsPage.java new file mode 100644 index 00000000..df5e00f0 --- /dev/null +++ b/src/com/gitblit/wicket/pages/HeadsPage.java @@ -0,0 +1,63 @@ +package com.gitblit.wicket.pages;
+
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.Repository;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.Utils;
+import com.gitblit.wicket.GitBlitWebApp;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.models.RefModel;
+
+
+public class HeadsPage extends RepositoryPage {
+
+ public HeadsPage(PageParameters params) {
+ super(params, "heads");
+
+ Repository r = getRepository();
+ List<RefModel> tags = JGitUtils.getHeads(r, -1);
+ r.close();
+
+ // shortlog
+ add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter()));
+
+ ListDataProvider<RefModel> tagsDp = new ListDataProvider<RefModel>(tags);
+ DataView<RefModel> tagView = new DataView<RefModel>("head", tagsDp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RefModel> item) {
+ final RefModel entry = item.getModelObject();
+ String date;
+ if (entry.getDate() != null) {
+ date = Utils.timeAgo(entry.getDate());
+ } else {
+ date = "";
+ }
+ Label headDateLabel = new Label("headDate", date);
+ item.add(headDateLabel);
+ WicketUtils.setCssClass(headDateLabel, Utils.timeAgoCss(entry.getDate()));
+
+ item.add(new LinkPanel("headName", "list name", entry.getDisplayName(), ShortLogPage.class, newCommitParameter(entry.getName())));
+
+ String clazz = counter % 2 == 0 ? "dark" : "light";
+ WicketUtils.setCssClass(item, clazz);
+ counter++;
+ }
+ };
+ tagView.setItemsPerPage(GitBlitWebApp.PAGING_ITEM_COUNT);
+ add(tagView);
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/LogPage.html b/src/com/gitblit/wicket/pages/LogPage.html new file mode 100644 index 00000000..3c1b54b9 --- /dev/null +++ b/src/com/gitblit/wicket/pages/LogPage.html @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- summary header -->
+ <div class="header" wicket:id="summary"></div>
+
+ <!-- log -->
+ <div wicket:id="commit">
+ <div class="header">
+ <b><span class="age" wicket:id="timeAgo"></span></b>
+ <span wicket:id="link"></span>
+ </div>
+ <div wicket:id="commitRefs"></div>
+ <div class="title_text">
+ <div class="log_link">commit | commitdiff | tree</div>
+ <span wicket:id="commitAuthor"></span>
+ <span wicket:id="commitDate"></span>
+ </div>
+ <div class="log_body" wicket:id="fullMessage"></div>
+ </div>
+
+ <div wicket:id="navigator"></div>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/LogPage.java b/src/com/gitblit/wicket/pages/LogPage.java new file mode 100644 index 00000000..325596ab --- /dev/null +++ b/src/com/gitblit/wicket/pages/LogPage.java @@ -0,0 +1,69 @@ +package com.gitblit.wicket.pages;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.Utils;
+import com.gitblit.wicket.GitBlitWebApp;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.panels.RefsPanel;
+
+
+public class LogPage extends RepositoryPage {
+
+ public LogPage(PageParameters params) {
+ super(params, "log");
+
+ Repository r = getRepository();
+ final Map<ObjectId, List<String>> allRefs = JGitUtils.getAllRefs(r);
+ List<RevCommit> commits = JGitUtils.getRevLog(r, 100);
+ r.close();
+
+ add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter()));
+
+ // log
+ ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
+ DataView<RevCommit> logView = new DataView<RevCommit>("commit", dp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<RevCommit> item) {
+ final RevCommit entry = item.getModelObject();
+ final Date date = JGitUtils.getCommitDate(entry);
+
+ item.add(new Label("timeAgo", Utils.timeAgo(date)));
+
+ item.add(new LinkPanel("link", "title", entry.getShortMessage(), CommitPage.class, newCommitParameter(entry.getName())));
+
+ item.add(new RefsPanel("commitRefs", entry, allRefs));
+
+ String author = entry.getAuthorIdent().getName();
+ item.add(createAuthorLabel("commitAuthor", author));
+
+ item.add(new Label("commitDate", GitBlitWebSession.get().formatDateTimeLong(date)));
+
+ item.add(new Label("fullMessage", WicketUtils.breakLines(entry.getFullMessage())).setEscapeModelStrings(false));
+ }
+ };
+ logView.setItemsPerPage(GitBlitWebApp.PAGING_ITEM_COUNT);
+ add(logView);
+ add(new PagingNavigator("navigator", logView));
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.html b/src/com/gitblit/wicket/pages/RepositoriesPage.html new file mode 100644 index 00000000..6a3054f1 --- /dev/null +++ b/src/com/gitblit/wicket/pages/RepositoriesPage.html @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <div wicket:id="pageHeader"></div>
+ <div class="index_include" wicket:id="indexInclude"></div>
+
+ <table class="project_list">
+ <tr>
+ <th wicket:id="orderByRepository">Repository</th>
+ <th wicket:id="orderByDescription">Description</th>
+ <th wicket:id="orderByOwner">Owner</th>
+ <th wicket:id="orderByDate">Last Change</th>
+ <th></th>
+ </tr>
+ <tbody>
+ <tr wicket:id="repository">
+ <td><div class="list" wicket:id="repositoryName"></div></td>
+ <td><div class="list" wicket:id="repositoryDescription"></div></td>
+ <td><i><span wicket:id="repositoryOwner"></span></i></td>
+ <td><span wicket:id="repositoryLastChange"></span></td>
+ <td></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.java b/src/com/gitblit/wicket/pages/RepositoriesPage.java new file mode 100644 index 00000000..1c880d9f --- /dev/null +++ b/src/com/gitblit/wicket/pages/RepositoriesPage.java @@ -0,0 +1,151 @@ +package com.gitblit.wicket.pages;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+import com.gitblit.StoredSettings;
+import com.gitblit.utils.Utils;
+import com.gitblit.wicket.BasePage;
+import com.gitblit.wicket.GitBlitWebApp;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.models.RepositoryModel;
+import com.gitblit.wicket.panels.PageFooter;
+import com.gitblit.wicket.panels.PageHeader;
+
+
+public class RepositoriesPage extends BasePage {
+
+ public RepositoriesPage() {
+ add(new PageHeader("pageHeader"));
+
+ add(new Label("indexInclude", StoredSettings.getString("indexMessage", "")).setEscapeModelStrings(false));
+
+ List<RepositoryModel> rows = GitBlitWebApp.get().getRepositories(getRequest());
+ DataProvider dp = new DataProvider(rows);
+ DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repository", dp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RepositoryModel> item) {
+ final RepositoryModel entry = item.getModelObject();
+ PageParameters pp = new PageParameters("p=" + entry.name);
+ item.add(new LinkPanel("repositoryName", "list", entry.name, SummaryPage.class, pp));
+ item.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
+ item.add(new Label("repositoryOwner", entry.owner));
+
+ String lastChange = Utils.timeAgo(entry.lastChange);
+ Label lastChangeLabel = new Label("repositoryLastChange", lastChange);
+ item.add(lastChangeLabel);
+ WicketUtils.setCssClass(lastChangeLabel, Utils.timeAgoCss(entry.lastChange));
+
+ String clazz = counter % 2 == 0 ? "dark" : "light";
+ WicketUtils.setCssClass(item, clazz);
+ counter++;
+ }
+ };
+ add(dataView);
+
+ add(newSort("orderByRepository", SortBy.repository, dp, dataView));
+ add(newSort("orderByDescription", SortBy.description, dp, dataView));
+ add(newSort("orderByOwner", SortBy.owner, dp, dataView));
+ add(newSort("orderByDate", SortBy.date, dp, dataView));
+
+ add(new PageFooter("pageFooter"));
+ }
+
+ protected enum SortBy {
+ repository, description, owner, date;
+ }
+
+ protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp, final DataView<?> dataView) {
+ return new OrderByBorder(wicketId, field.name(), dp) {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void onSortChanged() {
+ dataView.setCurrentPage(0);
+ }
+ };
+ }
+
+ private class DataProvider extends SortableDataProvider<RepositoryModel> {
+ private static final long serialVersionUID = 1L;
+ private List<RepositoryModel> list = null;
+
+ protected DataProvider(List<RepositoryModel> list) {
+ this.list = list;
+ setSort(SortBy.date.name(), false);
+ }
+
+ @Override
+ public int size() {
+ if (list == null)
+ return 0;
+ return list.size();
+ }
+
+ @Override
+ public IModel<RepositoryModel> model(RepositoryModel header) {
+ return new Model<RepositoryModel>(header);
+ }
+
+ @Override
+ public Iterator<RepositoryModel> iterator(int first, int count) {
+ SortParam sp = getSort();
+ String prop = sp.getProperty();
+ final boolean asc = sp.isAscending();
+
+ if (prop == null || prop.equals(SortBy.date.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.lastChange.compareTo(o2.lastChange);
+ return o2.lastChange.compareTo(o1.lastChange);
+ }
+ });
+ } else if (prop.equals(SortBy.repository.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.name.compareTo(o2.name);
+ return o2.name.compareTo(o1.name);
+ }
+ });
+ } else if (prop.equals(SortBy.owner.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.owner.compareTo(o2.owner);
+ return o2.owner.compareTo(o1.owner);
+ }
+ });
+ } else if (prop.equals(SortBy.description.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.description.compareTo(o2.description);
+ return o2.description.compareTo(o1.description);
+ }
+ });
+ }
+ return list.subList(first, first + count).iterator();
+ }
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/ShortLogPage.html b/src/com/gitblit/wicket/pages/ShortLogPage.html new file mode 100644 index 00000000..b10e90d6 --- /dev/null +++ b/src/com/gitblit/wicket/pages/ShortLogPage.html @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- shortlog -->
+ <div class="header" wicket:id="summary"></div>
+
+ <table class="project_list">
+ <tbody>
+ <tr wicket:id="commit">
+ <td><span wicket:id="commitDate"></span></td>
+ <td><i><span wicket:id="commitAuthor"></span></i></td>
+ <td><div wicket:id="commitShortMessage"></div></td>
+ <td><div wicket:id="commitRefs"></div></td>
+ <td><span wicket:id="commitLinks"></span></td>
+ </tr>
+ <tr>
+ <td colspan="4"><div wicket:id="navigator"></div></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/ShortLogPage.java b/src/com/gitblit/wicket/pages/ShortLogPage.java new file mode 100644 index 00000000..220874e8 --- /dev/null +++ b/src/com/gitblit/wicket/pages/ShortLogPage.java @@ -0,0 +1,76 @@ +package com.gitblit.wicket.pages;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.GitBlitWebApp;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.panels.RefsPanel;
+import com.gitblit.wicket.panels.ShortLogLinksPanel;
+
+
+public class ShortLogPage extends RepositoryPage {
+
+ public ShortLogPage(PageParameters params) {
+ super(params, "shortlog");
+
+ Repository r = getRepository();
+ final Map<ObjectId, List<String>> allRefs = JGitUtils.getAllRefs(r);
+ List<RevCommit> commits = JGitUtils.getRevLog(r, 100);
+ r.close();
+
+ // shortlog
+ add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter()));
+
+ ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
+ DataView<RevCommit> shortlogView = new DataView<RevCommit>("commit", dp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RevCommit> item) {
+ final RevCommit entry = item.getModelObject();
+ final Date date = JGitUtils.getCommitDate(entry);
+
+ item.add(createShortlogDateLabel("commitDate", date));
+
+ String author = entry.getAuthorIdent().getName();
+ item.add(createAuthorLabel("commitAuthor", author));
+
+ String shortMessage = entry.getShortMessage();
+ String trimmedMessage = trimShortLog(shortMessage);
+ LinkPanel shortlog = new LinkPanel("commitShortMessage", "list subject", trimmedMessage, CommitPage.class, newCommitParameter(entry.getName()));
+ if (!shortMessage.equals(trimmedMessage)) {
+ WicketUtils.setHtmlTitle(shortlog, shortMessage);
+ }
+ item.add(shortlog);
+
+ item.add(new RefsPanel("commitRefs", entry, allRefs));
+
+ item.add(new ShortLogLinksPanel("commitLinks", repositoryName, entry.getName()));
+
+ String clazz = counter % 2 == 0 ? "dark" : "light";
+ WicketUtils.setCssClass(item, clazz);
+ counter++;
+ }
+ };
+ shortlogView.setItemsPerPage(GitBlitWebApp.PAGING_ITEM_COUNT);
+ add(shortlogView);
+ add(new PagingNavigator("navigator", shortlogView));
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/SummaryPage.html b/src/com/gitblit/wicket/pages/SummaryPage.html new file mode 100644 index 00000000..3eab0a1e --- /dev/null +++ b/src/com/gitblit/wicket/pages/SummaryPage.html @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- repository info -->
+ <div class="title"> </div>
+ <table class="projects_list">
+ <tr id="metadata_desc"><td>description</td><td><span wicket:id="repositoryDescription">Message goes here</span></td></tr>
+ <tr id="metadata_owner"><td>owner</td><td><span wicket:id="repositoryOwner">Message goes here</span></td></tr>
+ <tr id="metadata_lchange"><td>last change</td><td><span wicket:id="repositoryLastChange">Message goes here</span></td></tr>
+ <tr class="metadata_url"><td>URL</td><td><span wicket:id="repositoryCloneUrl">Message goes here</span></td></tr>
+ </table>
+
+
+ <!-- shortlog -->
+ <div class="header" wicket:id="shortlog"></div>
+
+ <table class="project_list">
+ <tbody>
+ <tr wicket:id="commit">
+ <td><span wicket:id="commitDate"></span></td>
+ <td><i><span wicket:id="commitAuthor"></span></i></td>
+ <td><div wicket:id="commitShortMessage"></div></td>
+ <td><div wicket:id="commitRefs"></div></td>
+ <td><span wicket:id="commitLinks"></span></td>
+ </tr>
+
+ <tr>
+ <td colspan="4"><div wicket:id="shortlogMore"></div></td>
+ </tr>
+ </tbody>
+ </table>
+
+
+ <!-- tags -->
+ <div class="header" wicket:id="tags"></div>
+
+ <table class="project_list">
+ <tbody>
+ <tr wicket:id="tag">
+ <td><i><span wicket:id="tagDate"></span></i></td>
+ <td><div wicket:id="tagName"></div></td>
+ <td><div wicket:id="tagDescription"></div></td>
+ <td><span wicket:id="tagLinks"></span></td>
+ </tr>
+
+ <tr>
+ <td colspan="4"><div wicket:id="tagsMore"></div></td>
+ </tr>
+ </tbody>
+ </table>
+
+
+ <!-- heads -->
+ <div class="header" wicket:id="heads"></div>
+
+ <table class="heads">
+ <tbody>
+ <tr wicket:id="head">
+ <td><i><span wicket:id="headDate"></span></i></td>
+ <td><div wicket:id="headName"></div></td>
+ <td><span wicket:id="headLinks"></span></td>
+ </tr>
+ </tbody>
+ </table>
+
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/SummaryPage.java b/src/com/gitblit/wicket/pages/SummaryPage.java new file mode 100644 index 00000000..84e78b4e --- /dev/null +++ b/src/com/gitblit/wicket/pages/SummaryPage.java @@ -0,0 +1,149 @@ +package com.gitblit.wicket.pages;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.GitBlitWebApp;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.models.RefModel;
+import com.gitblit.wicket.panels.HeadLinksPanel;
+import com.gitblit.wicket.panels.RefsPanel;
+import com.gitblit.wicket.panels.ShortLogLinksPanel;
+import com.gitblit.wicket.panels.TagLinksPanel;
+
+
+public class SummaryPage extends RepositoryPage {
+
+ public SummaryPage(PageParameters params) {
+ super(params, "summary");
+
+ Repository r = getRepository();
+ final Map<ObjectId, List<String>> allRefs = JGitUtils.getAllRefs(r);
+
+ String owner = JGitUtils.getRepositoryOwner(r);
+ GitBlitWebSession session = GitBlitWebSession.get();
+ String lastchange = session.formatDateTimeLong(JGitUtils.getLastChange(r));
+ String cloneurl = GitBlitWebApp.get().getCloneUrl(repositoryName);
+
+ // repository description
+ add(new Label("repositoryDescription", description));
+ add(new Label("repositoryOwner", owner));
+ add(new Label("repositoryLastChange", lastchange));
+ add(new Label("repositoryCloneUrl", cloneurl));
+
+ int summaryCount = 16;
+
+ // shortlog
+ add(new LinkPanel("shortlog", "title", "shortlog", ShortLogPage.class, newRepositoryParameter()));
+
+ List<RevCommit> commits = JGitUtils.getRevLog(r, summaryCount);
+ ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
+ DataView<RevCommit> shortlogView = new DataView<RevCommit>("commit", dp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RevCommit> item) {
+ RevCommit entry = item.getModelObject();
+ Date date = JGitUtils.getCommitDate(entry);
+
+ item.add(createShortlogDateLabel("commitDate", date));
+
+ String author = entry.getAuthorIdent().getName();
+ item.add(createAuthorLabel("commitAuthor", author));
+
+ String shortMessage = entry.getShortMessage();
+ String trimmedMessage = trimShortLog(shortMessage);
+ LinkPanel shortlog = new LinkPanel("commitShortMessage", "list subject", trimmedMessage, CommitPage.class, newCommitParameter(entry.getName()));
+ if (!shortMessage.equals(trimmedMessage)) {
+ WicketUtils.setHtmlTitle(shortlog, shortMessage);
+ }
+ item.add(shortlog);
+
+ item.add(new RefsPanel("commitRefs", entry, allRefs));
+
+ item.add(new ShortLogLinksPanel("commitLinks", repositoryName, entry.getName()));
+
+ setAlternatingBackground(item, counter);
+ counter++;
+ }
+ };
+ add(shortlogView);
+ add(new LinkPanel("shortlogMore", "link", "...", ShortLogPage.class, newRepositoryParameter()));
+
+ // tags
+ List<RefModel> tags = JGitUtils.getTags(r, summaryCount);
+ add(new LinkPanel("tags", "title", "tags", TagsPage.class, newRepositoryParameter()));
+
+ ListDataProvider<RefModel> tagsDp = new ListDataProvider<RefModel>(tags);
+ DataView<RefModel> tagView = new DataView<RefModel>("tag", tagsDp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RefModel> item) {
+ final RefModel entry = item.getModelObject();
+
+ item.add(createDateLabel("tagDate", entry.getDate()));
+
+ item.add(new LinkPanel("tagName", "list name", entry.getDisplayName(), CommitPage.class, newCommitParameter(entry.getCommitId().getName())));
+
+ if (entry.getCommitId().equals(entry.getObjectId())) {
+ // lightweight tag on commit object
+ item.add(new Label("tagDescription", ""));
+ } else {
+ // tag object
+ item.add(new LinkPanel("tagDescription", "list subject", entry.getShortLog(), TagPage.class, newCommitParameter(entry.getObjectId().getName())));
+ }
+
+ item.add(new TagLinksPanel("tagLinks", repositoryName, entry));
+
+ setAlternatingBackground(item, counter);
+ counter++;
+ }
+ };
+ add(tagView);
+ add(new LinkPanel("tagsMore", "link", "...", TagsPage.class, newRepositoryParameter()));
+ // heads
+ List<RefModel> heads = JGitUtils.getHeads(r, summaryCount);
+ add(new LinkPanel("heads", "title", "heads", HeadsPage.class, newRepositoryParameter()));
+
+ ListDataProvider<RefModel> headsDp = new ListDataProvider<RefModel>(heads);
+ DataView<RefModel> headsView = new DataView<RefModel>("head", headsDp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RefModel> item) {
+ final RefModel entry = item.getModelObject();
+
+ item.add(createDateLabel("headDate", entry.getDate()));
+
+ item.add(new LinkPanel("headName", "list name", entry.getDisplayName(), ShortLogPage.class, newCommitParameter(entry.getName())));
+
+ item.add(new HeadLinksPanel("headLinks", repositoryName, entry));
+
+ setAlternatingBackground(item, counter);
+ counter++;
+ }
+ };
+ add(headsView);
+
+ // close the repository
+ r.close();
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/TagPage.html b/src/com/gitblit/wicket/pages/TagPage.html new file mode 100644 index 00000000..ae2c99c2 --- /dev/null +++ b/src/com/gitblit/wicket/pages/TagPage.html @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- summary header -->
+ <div class="header" wicket:id="commit"></div>
+
+ <!-- commit info -->
+ <div class="title_text">
+ <table class="object_header">
+ <tr><td>object</td><td><span wicket:id="tagId">Message goes here</span></td></tr>
+ <tr><td>author</td><td><span wicket:id="tagAuthor">Message goes here</span></td></tr>
+ <tr><td></td><td><span wicket:id="tagDate">Message goes here</span></td></tr>
+ </table>
+ </div>
+
+ <!-- full message -->
+ <div class="page_body" wicket:id="fullMessage"></div>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/TagPage.java b/src/com/gitblit/wicket/pages/TagPage.java new file mode 100644 index 00000000..f098c1e3 --- /dev/null +++ b/src/com/gitblit/wicket/pages/TagPage.java @@ -0,0 +1,36 @@ +package com.gitblit.wicket.pages;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+
+
+public class TagPage extends RepositoryPage {
+
+ public TagPage(PageParameters params) {
+ super(params, "tag");
+
+ Repository r = getRepository();
+ RevCommit c = JGitUtils.getCommit(r, commitId);
+
+ add(new LinkPanel("commit", "title", c.getName(), CommitPage.class, newCommitParameter()));
+
+ add(new LinkPanel("tagId", "list", c.getName(), CommitPage.class, newCommitParameter(c.getName())));
+ add(new Label("tagAuthor", JGitUtils.getDisplayName(c.getAuthorIdent())));
+ String authorDate = GitBlitWebSession.get().formatDateTimeLong(c.getAuthorIdent().getWhen());
+ add(new Label("tagDate", authorDate));
+
+ addFullText("fullMessage", c.getFullMessage(), true);
+
+ r.close();
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/TagsPage.html b/src/com/gitblit/wicket/pages/TagsPage.html new file mode 100644 index 00000000..314eec77 --- /dev/null +++ b/src/com/gitblit/wicket/pages/TagsPage.html @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- shortlog -->
+ <div class="header" wicket:id="summary"></div>
+
+ <table class="tags">
+ <tbody>
+ <tr wicket:id="tag">
+ <td><i><span wicket:id="tagDate"></span></i></td>
+ <td><div wicket:id="tagName"></div></td>
+ <td><div wicket:id="tagDescription"></div></td>
+ <td><span wicket:id="tagLinks"></span></td>
+ </tr>
+ <tr>
+ <td colspan="4"><div wicket:id="navigator"></div></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/TagsPage.java b/src/com/gitblit/wicket/pages/TagsPage.java new file mode 100644 index 00000000..85c0455c --- /dev/null +++ b/src/com/gitblit/wicket/pages/TagsPage.java @@ -0,0 +1,64 @@ +package com.gitblit.wicket.pages;
+
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.Repository;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.GitBlitWebApp;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.models.RefModel;
+import com.gitblit.wicket.panels.TagLinksPanel;
+
+
+public class TagsPage extends RepositoryPage {
+
+ public TagsPage(PageParameters params) {
+ super(params, "tags");
+ Repository r = getRepository();
+ List<RefModel> tags = JGitUtils.getTags(r, -1);
+ r.close();
+
+ // shortlog
+ add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter()));
+
+ ListDataProvider<RefModel> tagsDp = new ListDataProvider<RefModel>(tags);
+ DataView<RefModel> tagView = new DataView<RefModel>("tag", tagsDp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RefModel> item) {
+ final RefModel entry = item.getModelObject();
+ item.add(createDateLabel("tagDate", entry.getDate()));
+
+ item.add(new LinkPanel("tagName", "list name", entry.getDisplayName(), CommitPage.class, newCommitParameter(entry.getObjectId().getName())));
+
+ if (entry.getCommitId().equals(entry.getObjectId())) {
+ // lightweight tag on commit object
+ item.add(new Label("tagDescription", ""));
+ } else {
+ // tag object
+ item.add(new LinkPanel("tagDescription", "list subject", entry.getShortLog(), TagPage.class, newCommitParameter(entry.getObjectId().getName())));
+ }
+
+ item.add(new TagLinksPanel("tagLinks", repositoryName, entry));
+
+ setAlternatingBackground(item, counter);
+ counter++;
+ }
+ };
+ tagView.setItemsPerPage(GitBlitWebApp.PAGING_ITEM_COUNT);
+ add(tagView);
+ add(new PagingNavigator("navigator", tagView));
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/pages/TreePage.html b/src/com/gitblit/wicket/pages/TreePage.html new file mode 100644 index 00000000..e01049c6 --- /dev/null +++ b/src/com/gitblit/wicket/pages/TreePage.html @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<body>
+ <!-- page header -->
+ <div wicket:id="pageHeader"></div>
+
+ <!-- page nav links -->
+ <div wicket:id="pageLinks"></div>
+
+ <!-- blob nav links -->
+ <div class="page_nav2">
+ <span wicket:id="historyLink"></span> | <span wicket:id="headLink"></span>
+ </div>
+
+ <!-- shortlog header -->
+ <div class="header" wicket:id="shortlog"></div>
+
+ <!-- breadcrumbs -->
+ <div wicket:id="breadcrumbs"></div>
+
+ <!-- changed paths -->
+ <div class="list_head"></div>
+ <table class="diff_tree">
+ <tr wicket:id="changedPath">
+ <td class="mode"><span wicket:id="pathPermissions"></span></td>
+ <td class="size"><span wicket:id="pathSize"></span></td>
+ <td><span wicket:id="pathName"></span></td>
+ <td><span wicket:id="treeLinks"></span></td>
+ </tr>
+ </table>
+
+ <!-- footer -->
+ <div wicket:id="pageFooter"></div>
+</body>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/TreePage.java b/src/com/gitblit/wicket/pages/TreePage.java new file mode 100644 index 00000000..a608bdda --- /dev/null +++ b/src/com/gitblit/wicket/pages/TreePage.java @@ -0,0 +1,89 @@ +package com.gitblit.wicket.pages;
+
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.ByteFormat;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.RepositoryPage;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.models.PathModel;
+import com.gitblit.wicket.panels.PathBreadcrumbsPanel;
+import com.gitblit.wicket.panels.TreeLinksPanel;
+
+
+public class TreePage extends RepositoryPage {
+
+ public TreePage(PageParameters params) {
+ super(params, "tree");
+
+ final String basePath = params.getString("f", null);
+
+ Repository r = getRepository();
+ RevCommit commit = JGitUtils.getCommit(r, commitId);
+ List<PathModel> paths = JGitUtils.getFilesInPath(r, basePath, commit);
+
+ // tree page links
+ add(new Label("historyLink", "history"));
+ add(new Label("headLink", "HEAD"));
+
+ add(new LinkPanel("shortlog", "title", commit.getShortMessage(), CommitPage.class, newCommitParameter()));
+
+ // breadcrumbs
+ if (basePath == null || basePath.trim().length() == 0) {
+ add(new Label("breadcrumbs", "").setVisible(false));
+ } else {
+ add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, basePath, commitId));
+ paths.add(0, PathModel.getParentPath(basePath, commitId));
+ }
+
+ final ByteFormat byteFormat = new ByteFormat();
+
+ // changed paths list
+ ListDataProvider<PathModel> pathsDp = new ListDataProvider<PathModel>(paths);
+ DataView<PathModel> pathsView = new DataView<PathModel>("changedPath", pathsDp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<PathModel> item) {
+ PathModel entry = item.getModelObject();
+ item.add(new Label("pathPermissions", JGitUtils.getPermissionsFromMode(entry.mode)));
+ if (entry.isParentPath) {
+ // parent .. path
+ item.add(new Label("pathSize", "").setVisible(false));
+ item.add(new LinkPanel("pathName", null, entry.name, TreePage.class, newPathParameter(entry.path)));
+ item.add(new Label("treeLinks", "").setVisible(false));
+ } else {
+ if (entry.isTree()) {
+ // folder/tree link
+ item.add(new Label("pathSize", "-"));
+ item.add(new LinkPanel("pathName", null, entry.name, TreePage.class, newPathParameter(entry.path)));
+ } else {
+ // blob link
+ item.add(new Label("pathSize", byteFormat.format(entry.size)));
+ item.add(new LinkPanel("pathName", "list", entry.name, BlobPage.class, newPathParameter(entry.path)));
+ }
+ item.add(new TreeLinksPanel("treeLinks", repositoryName, entry));
+ }
+ String clazz = counter % 2 == 0 ? "dark" : "light";
+ WicketUtils.setCssClass(item, clazz);
+ counter++;
+ }
+ };
+ add(pathsView);
+
+ // close repository
+ r.close();
+
+ // footer
+ addFooter();
+ }
+}
diff --git a/src/com/gitblit/wicket/panels/HeadLinksPanel.html b/src/com/gitblit/wicket/panels/HeadLinksPanel.html new file mode 100644 index 00000000..4849e8e2 --- /dev/null +++ b/src/com/gitblit/wicket/panels/HeadLinksPanel.html @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <div class="link">
+ <span wicket:id="shortlog"></span> | <span wicket:id="log"></span> | <span wicket:id="tree"></span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/HeadLinksPanel.java b/src/com/gitblit/wicket/panels/HeadLinksPanel.java new file mode 100644 index 00000000..4f4c9d7e --- /dev/null +++ b/src/com/gitblit/wicket/panels/HeadLinksPanel.java @@ -0,0 +1,23 @@ +package com.gitblit.wicket.panels;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.models.RefModel;
+import com.gitblit.wicket.pages.LogPage;
+import com.gitblit.wicket.pages.ShortLogPage;
+
+
+public class HeadLinksPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public HeadLinksPanel(String id, String repositoryName, RefModel tag) {
+ super(id);
+ add(new LinkPanel("shortlog", null, "shortlog", ShortLogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
+ add(new LinkPanel("log", null, "log", LogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
+ add(new Label("tree", "tree"));
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PageFooter.html b/src/com/gitblit/wicket/panels/PageFooter.html new file mode 100644 index 00000000..6eed4b3c --- /dev/null +++ b/src/com/gitblit/wicket/panels/PageFooter.html @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <div class="page_footer">
+ <div class="cachetime"><span wicket:id="cacheTime"></span></div>
+ <div class="page_footer_text"><span wicket:id="footerText"></span></div>
+ <a title="git homepage" href="http://git-scm.com/">Git</a>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PageFooter.java b/src/com/gitblit/wicket/panels/PageFooter.java new file mode 100644 index 00000000..91a1f57c --- /dev/null +++ b/src/com/gitblit/wicket/panels/PageFooter.java @@ -0,0 +1,28 @@ +package com.gitblit.wicket.panels;
+
+import java.util.Date;
+
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.StoredSettings;
+import com.gitblit.wicket.GitBlitWebSession;
+
+
+public class PageFooter extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public PageFooter(String id) {
+ this(id, "");
+ }
+
+ public PageFooter(String id, String description) {
+ super(id);
+ add(new Label("cacheTime", "Page Last Updated: " + GitBlitWebSession.get().formatDateTimeLong(new Date())));
+ add(new Label("footerText", description));
+ if (StoredSettings.getBoolean("aggressiveGC", false)) {
+ System.gc();
+ }
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PageHeader.html b/src/com/gitblit/wicket/panels/PageHeader.html new file mode 100644 index 00000000..83edb994 --- /dev/null +++ b/src/com/gitblit/wicket/panels/PageHeader.html @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <head>
+ <title wicket:id="title">Message goes here</title>
+ <link rel="stylesheet" type="text/css" href="gitblit.css"/>
+ <link rel="stylesheet" type="text/css" href="gitweb.css"/>
+ <link rel="shortcut icon" href="git-favicon.png" type="image/png" />
+ </head>
+
+ <div class="page_header">
+ <a title="gitblit homepage" href="http://gitblit.com/"><img src="gitblt-logo.png" width="91" height="31" alt="gitblit" class="logo"/></a><a href="/"><span wicket:id="siteName">name</span></a> / <span wicket:id="repositoryName">name</span> <span wicket:id="pageName">name</span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PageHeader.java b/src/com/gitblit/wicket/panels/PageHeader.java new file mode 100644 index 00000000..c375758c --- /dev/null +++ b/src/com/gitblit/wicket/panels/PageHeader.java @@ -0,0 +1,41 @@ +package com.gitblit.wicket.panels;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+
+import com.gitblit.Constants;
+import com.gitblit.StoredSettings;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.pages.SummaryPage;
+
+
+public class PageHeader extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public PageHeader(String id) {
+ this(id, "", "");
+ }
+
+ public PageHeader(String id, String repositoryName, String page) {
+ super(id);
+ if (repositoryName != null && repositoryName.trim().length() > 0) {
+ add(new Label("title", getServerName() + " - " + repositoryName));
+ } else {
+ add(new Label("title", getServerName()));
+ }
+ add(new Label("siteName", StoredSettings.getString("siteName", Constants.NAME)));
+ add(new LinkPanel("repositoryName", null, repositoryName, SummaryPage.class, new PageParameters("p=" + repositoryName)));
+ add(new Label("pageName", page));
+ }
+
+ protected String getServerName() {
+ ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
+ HttpServletRequest req = servletWebRequest.getHttpServletRequest();
+ return req.getServerName();
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PageLinksPanel.html b/src/com/gitblit/wicket/panels/PageLinksPanel.html new file mode 100644 index 00000000..66c3ce7a --- /dev/null +++ b/src/com/gitblit/wicket/panels/PageLinksPanel.html @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <!-- page nav links -->
+ <div class="page_nav">
+ <span wicket:id="summary"></span> | <span wicket:id="shortlog"></span> | <span wicket:id="log"></span> | <span wicket:id="commit"></span> | <span wicket:id="commitdiff"></span> | <span wicket:id="tree"></span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PageLinksPanel.java b/src/com/gitblit/wicket/panels/PageLinksPanel.java new file mode 100644 index 00000000..f72b8800 --- /dev/null +++ b/src/com/gitblit/wicket/panels/PageLinksPanel.java @@ -0,0 +1,61 @@ +package com.gitblit.wicket.panels;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.LogPage;
+import com.gitblit.wicket.pages.ShortLogPage;
+import com.gitblit.wicket.pages.SummaryPage;
+import com.gitblit.wicket.pages.TreePage;
+
+
+public class PageLinksPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public PageLinksPanel(String id, String repositoryName, String pageName) {
+ super(id);
+ // summary
+ if (pageName.equals("summary")) {
+ add(new Label("summary", pageName));
+ } else {
+ add(new LinkPanel("summary", null, "summary", SummaryPage.class, new PageParameters("p=" + repositoryName)));
+ }
+
+ // shortlog
+ if (pageName.equals("shortlog")) {
+ add(new Label("shortlog", pageName));
+ } else {
+ add(new LinkPanel("shortlog", null, "shortlog", ShortLogPage.class, new PageParameters("p=" + repositoryName)));
+ }
+
+ // log
+ if (pageName.equals("log")) {
+ add(new Label("log", pageName));
+ } else {
+ add(new LinkPanel("log", null, "log", LogPage.class, new PageParameters("p=" + repositoryName)));
+ }
+
+ // commit
+ if (pageName.equals("commit")) {
+ add(new Label("commit", pageName));
+ } else {
+ add(new LinkPanel("commit", null, "commit", CommitPage.class, new PageParameters("p=" + repositoryName + ",h=HEAD")));
+ }
+ // commitdiff
+ if (pageName.equals("commitdiff")) {
+ add(new Label("commitdiff", pageName));
+ } else {
+ add(new Label("commitdiff", "commitdiff"));
+ }
+ // tree
+ if (pageName.equals("tree")) {
+ add(new Label("tree", pageName));
+ } else {
+ add(new LinkPanel("tree", null, "tree", TreePage.class, new PageParameters("p=" + repositoryName + ",h=HEAD")));
+ }
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.html b/src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.html new file mode 100644 index 00000000..ee8bca22 --- /dev/null +++ b/src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.html @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <!-- page path links -->
+ <div class="page_path">
+ <span wicket:id="path">
+ <span wicket:id="pathLink"></span> <span wicket:id="pathSeparator"></span>
+ </span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.java b/src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.java new file mode 100644 index 00000000..5ce356a2 --- /dev/null +++ b/src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.java @@ -0,0 +1,79 @@ +package com.gitblit.wicket.panels;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.pages.TreePage;
+
+
+public class PathBreadcrumbsPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String ROOT = "--ROOT--";
+
+ public PathBreadcrumbsPanel(String id, final String repositoryName, String pathName, final String commitId) {
+ super(id);
+ List<BreadCrumb> crumbs = new ArrayList<BreadCrumb>();
+ crumbs.add(new BreadCrumb("[" + repositoryName + "]", ROOT, false));
+
+ String[] paths = pathName.split("/");
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < paths.length; i++) {
+ String path = paths[i];
+ sb.append(path);
+ crumbs.add(new BreadCrumb(path, sb.toString(), (i == (paths.length - 1))));
+ sb.append("/");
+ }
+
+ ListDataProvider<BreadCrumb> crumbsDp = new ListDataProvider<BreadCrumb>(crumbs);
+ DataView<BreadCrumb> pathsView = new DataView<BreadCrumb>("path", crumbsDp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<BreadCrumb> item) {
+ final BreadCrumb entry = item.getModelObject();
+ String path = entry.getPath();
+ String parameters = "p=" + repositoryName + ",h=" + commitId;
+ if (path != null) {
+ parameters += ",f=" + path;
+ }
+
+ item.add(new LinkPanel("pathLink", null, entry.name, TreePage.class, new PageParameters(parameters)));
+ item.add(new Label("pathSeparator", entry.isLeaf ? "":"/"));
+ }
+ };
+ add(pathsView);
+ }
+
+ private class BreadCrumb implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ final String name;
+ final String path;
+ final boolean isLeaf;
+
+ BreadCrumb(String name, String path, boolean isLeaf) {
+ this.name = name;
+ this.path = path;
+ this.isLeaf = isLeaf;
+ }
+
+ String getPath() {
+ if (path.equals(ROOT)) {
+ return null;
+ }
+ return path;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PathLinksPanel.html b/src/com/gitblit/wicket/panels/PathLinksPanel.html new file mode 100644 index 00000000..08327b1b --- /dev/null +++ b/src/com/gitblit/wicket/panels/PathLinksPanel.html @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <div class="link">
+ <span wicket:id="diff"></span> | <span wicket:id="blob"></span> | <span wicket:id="history"></span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/PathLinksPanel.java b/src/com/gitblit/wicket/panels/PathLinksPanel.java new file mode 100644 index 00000000..fa8bdca6 --- /dev/null +++ b/src/com/gitblit/wicket/panels/PathLinksPanel.java @@ -0,0 +1,22 @@ +package com.gitblit.wicket.panels;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.models.PathModel;
+import com.gitblit.wicket.pages.BlobPage;
+
+
+public class PathLinksPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public PathLinksPanel(String id, String repositoryName, PathModel path) {
+ super(id);
+ add(new Label("diff", "diff"));
+ add(new LinkPanel("blob", null, "blob", BlobPage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
+ add(new Label("history", "history"));
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/RefsPanel.html b/src/com/gitblit/wicket/panels/RefsPanel.html new file mode 100644 index 00000000..e7be7c54 --- /dev/null +++ b/src/com/gitblit/wicket/panels/RefsPanel.html @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <span class="refs" wicket:id="ref">
+ <span wicket:id="refName">ref</span>
+ </span>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/RefsPanel.java b/src/com/gitblit/wicket/panels/RefsPanel.java new file mode 100644 index 00000000..5dec57fe --- /dev/null +++ b/src/com/gitblit/wicket/panels/RefsPanel.java @@ -0,0 +1,66 @@ +package com.gitblit.wicket.panels;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.wicket.WicketUtils;
+
+
+public class RefsPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public RefsPanel(String id, Repository r, RevCommit c) {
+ this(id, c, JGitUtils.getAllRefs(r));
+ }
+
+ public RefsPanel(String id, RevCommit c, Map<ObjectId, List<String>> refs) {
+ super(id);
+ List<String> refNames = refs.get(c.getId());
+ if (refNames == null) {
+ refNames = new ArrayList<String>();
+ }
+ Collections.sort(refNames);
+ ListDataProvider<String> refsDp = new ListDataProvider<String>(refNames);
+ DataView<String> refsView = new DataView<String>("ref", refsDp) {
+ private static final long serialVersionUID = 1L;
+ public void populateItem(final Item<String> item) {
+ String entry = item.getModelObject();
+ Component c = null;
+ if (entry.startsWith(Constants.R_HEADS)) {
+ // local head
+ c = new Label("refName", entry.substring(Constants.R_HEADS.length()));
+ WicketUtils.setCssClass(c, "head");
+ } else if (entry.startsWith(Constants.R_REMOTES)) {
+ // remote head
+ c = new Label("refName", entry.substring(Constants.R_REMOTES.length()));
+ WicketUtils.setCssClass(c, "ref");
+ } else if (entry.startsWith(Constants.R_TAGS)) {
+ // tag
+ c = new Label("refName", entry.substring(Constants.R_TAGS.length()));
+ WicketUtils.setCssClass(c, "tag");
+ } else {
+ // other
+ c = new Label("refName", entry);
+ }
+ WicketUtils.setHtmlTitle(c, entry);
+ item.add(c);
+ }
+ };
+ add(refsView);
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/ShortLogLinksPanel.html b/src/com/gitblit/wicket/panels/ShortLogLinksPanel.html new file mode 100644 index 00000000..75d6b1ca --- /dev/null +++ b/src/com/gitblit/wicket/panels/ShortLogLinksPanel.html @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <div class="link">
+ <span wicket:id="commit"></span> | <span wicket:id="commitdiff"></span> | <span wicket:id="tree"></span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/ShortLogLinksPanel.java b/src/com/gitblit/wicket/panels/ShortLogLinksPanel.java new file mode 100644 index 00000000..58ec37ac --- /dev/null +++ b/src/com/gitblit/wicket/panels/ShortLogLinksPanel.java @@ -0,0 +1,23 @@ +package com.gitblit.wicket.panels;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.TreePage;
+
+
+public class ShortLogLinksPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public ShortLogLinksPanel(String id, String repositoryName, String commitId) {
+ super(id);
+
+ add(new LinkPanel("commit", null, "commit", CommitPage.class, new PageParameters("p=" + repositoryName + ",h=" + commitId)));
+ add(new Label("commitdiff", "commitdiff"));
+ add(new LinkPanel("tree", null, "tree", TreePage.class, new PageParameters("p=" + repositoryName + ",h=" + commitId)));
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/TagLinksPanel.html b/src/com/gitblit/wicket/panels/TagLinksPanel.html new file mode 100644 index 00000000..30934085 --- /dev/null +++ b/src/com/gitblit/wicket/panels/TagLinksPanel.html @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <div class="link">
+ <span wicket:id="commit"></span> | <span wicket:id="shortlog"></span> | <span wicket:id="log"></span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/TagLinksPanel.java b/src/com/gitblit/wicket/panels/TagLinksPanel.java new file mode 100644 index 00000000..73a9c3ae --- /dev/null +++ b/src/com/gitblit/wicket/panels/TagLinksPanel.java @@ -0,0 +1,23 @@ +package com.gitblit.wicket.panels;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.models.RefModel;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.LogPage;
+import com.gitblit.wicket.pages.ShortLogPage;
+
+
+public class TagLinksPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public TagLinksPanel(String id, String repositoryName, RefModel tag) {
+ super(id);
+ add(new LinkPanel("commit", null, "commit", CommitPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getCommitId().getName())));
+ add(new LinkPanel("shortlog", null, "shortlog", ShortLogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
+ add(new LinkPanel("log", null, "log", LogPage.class, new PageParameters("p=" + repositoryName + ",h=" + tag.getName())));
+ }
+}
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/TreeLinksPanel.html b/src/com/gitblit/wicket/panels/TreeLinksPanel.html new file mode 100644 index 00000000..d0c3b7f3 --- /dev/null +++ b/src/com/gitblit/wicket/panels/TreeLinksPanel.html @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<wicket:panel>
+ <div class="link">
+ <span wicket:id="link"></span> | <span wicket:id="history"></span> | <span wicket:id="raw"></span>
+ </div>
+</wicket:panel>
+</html>
\ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/TreeLinksPanel.java b/src/com/gitblit/wicket/panels/TreeLinksPanel.java new file mode 100644 index 00000000..21da66c9 --- /dev/null +++ b/src/com/gitblit/wicket/panels/TreeLinksPanel.java @@ -0,0 +1,29 @@ +package com.gitblit.wicket.panels;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.models.PathModel;
+import com.gitblit.wicket.pages.BlobPage;
+import com.gitblit.wicket.pages.TreePage;
+
+
+public class TreeLinksPanel extends Panel {
+
+ private static final long serialVersionUID = 1L;
+
+ public TreeLinksPanel(String id, String repositoryName, PathModel path) {
+ super(id);
+ if (path.isTree()) {
+ add(new LinkPanel("link", null, "tree", TreePage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
+ add(new Label("history", "history"));
+ add(new Label("raw", "").setVisible(false));
+ } else {
+ add(new LinkPanel("link", null, "blob", BlobPage.class, new PageParameters("p=" + repositoryName + ",h=" + path.commitId + ",f=" + path.path)));
+ add(new Label("history", "history"));
+ add(new Label("raw", "raw"));
+ }
+ }
+}
\ No newline at end of file |