From 5fe7df81eb38dc66f2cfc4bf1973863a19f55cf2 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 4 Apr 2011 09:10:51 -0400 Subject: Initial import of Git:Blit. Change-Id: Ifce000c85c8947c3a768e782c841e41a8953d314 --- src/com/gitblit/Build.java | 168 ++++++++ src/com/gitblit/Constants.java | 12 + src/com/gitblit/GitBlitServer.java | 393 +++++++++++++++++++ src/com/gitblit/Launcher.java | 117 ++++++ src/com/gitblit/MakeRepository.java | 51 +++ src/com/gitblit/StoredSettings.java | 130 +++++++ src/com/gitblit/tests/JGitUtilsTest.java | 71 ++++ src/com/gitblit/utils/ByteFormat.java | 82 ++++ src/com/gitblit/utils/JGitUtils.java | 430 +++++++++++++++++++++ src/com/gitblit/utils/Utils.java | 119 ++++++ src/com/gitblit/wicket/BasePage.java | 69 ++++ src/com/gitblit/wicket/GitBlitWebApp.java | 143 +++++++ src/com/gitblit/wicket/GitBlitWebSession.java | 74 ++++ src/com/gitblit/wicket/LinkPanel.html | 6 + src/com/gitblit/wicket/LinkPanel.java | 44 +++ src/com/gitblit/wicket/RepositoryPage.java | 118 ++++++ src/com/gitblit/wicket/SecuredPage.java | 11 + src/com/gitblit/wicket/WicketUtils.java | 35 ++ src/com/gitblit/wicket/models/PathModel.java | 45 +++ src/com/gitblit/wicket/models/RefModel.java | 54 +++ src/com/gitblit/wicket/models/RepositoryModel.java | 20 + src/com/gitblit/wicket/pages/BlobPage.html | 31 ++ src/com/gitblit/wicket/pages/BlobPage.java | 94 +++++ src/com/gitblit/wicket/pages/CommitPage.html | 51 +++ src/com/gitblit/wicket/pages/CommitPage.java | 106 +++++ src/com/gitblit/wicket/pages/HeadsPage.html | 26 ++ src/com/gitblit/wicket/pages/HeadsPage.java | 63 +++ src/com/gitblit/wicket/pages/LogPage.html | 33 ++ src/com/gitblit/wicket/pages/LogPage.java | 69 ++++ src/com/gitblit/wicket/pages/RepositoriesPage.html | 29 ++ src/com/gitblit/wicket/pages/RepositoriesPage.java | 151 ++++++++ src/com/gitblit/wicket/pages/ShortLogPage.html | 31 ++ src/com/gitblit/wicket/pages/ShortLogPage.java | 76 ++++ src/com/gitblit/wicket/pages/SummaryPage.html | 76 ++++ src/com/gitblit/wicket/pages/SummaryPage.java | 149 +++++++ src/com/gitblit/wicket/pages/TagPage.html | 28 ++ src/com/gitblit/wicket/pages/TagPage.java | 36 ++ src/com/gitblit/wicket/pages/TagsPage.html | 30 ++ src/com/gitblit/wicket/pages/TagsPage.java | 64 +++ src/com/gitblit/wicket/pages/TreePage.html | 35 ++ src/com/gitblit/wicket/pages/TreePage.java | 89 +++++ src/com/gitblit/wicket/panels/HeadLinksPanel.html | 8 + src/com/gitblit/wicket/panels/HeadLinksPanel.java | 23 ++ src/com/gitblit/wicket/panels/PageFooter.html | 10 + src/com/gitblit/wicket/panels/PageFooter.java | 28 ++ src/com/gitblit/wicket/panels/PageHeader.html | 15 + src/com/gitblit/wicket/panels/PageHeader.java | 41 ++ src/com/gitblit/wicket/panels/PageLinksPanel.html | 9 + src/com/gitblit/wicket/panels/PageLinksPanel.java | 61 +++ .../wicket/panels/PathBreadcrumbsPanel.html | 11 + .../wicket/panels/PathBreadcrumbsPanel.java | 79 ++++ src/com/gitblit/wicket/panels/PathLinksPanel.html | 8 + src/com/gitblit/wicket/panels/PathLinksPanel.java | 22 ++ src/com/gitblit/wicket/panels/RefsPanel.html | 8 + src/com/gitblit/wicket/panels/RefsPanel.java | 66 ++++ .../gitblit/wicket/panels/ShortLogLinksPanel.html | 8 + .../gitblit/wicket/panels/ShortLogLinksPanel.java | 23 ++ src/com/gitblit/wicket/panels/TagLinksPanel.html | 8 + src/com/gitblit/wicket/panels/TagLinksPanel.java | 23 ++ src/com/gitblit/wicket/panels/TreeLinksPanel.html | 8 + src/com/gitblit/wicket/panels/TreeLinksPanel.java | 29 ++ 61 files changed, 3947 insertions(+) create mode 100644 src/com/gitblit/Build.java create mode 100644 src/com/gitblit/Constants.java create mode 100644 src/com/gitblit/GitBlitServer.java create mode 100644 src/com/gitblit/Launcher.java create mode 100644 src/com/gitblit/MakeRepository.java create mode 100644 src/com/gitblit/StoredSettings.java create mode 100644 src/com/gitblit/tests/JGitUtilsTest.java create mode 100644 src/com/gitblit/utils/ByteFormat.java create mode 100644 src/com/gitblit/utils/JGitUtils.java create mode 100644 src/com/gitblit/utils/Utils.java create mode 100644 src/com/gitblit/wicket/BasePage.java create mode 100644 src/com/gitblit/wicket/GitBlitWebApp.java create mode 100644 src/com/gitblit/wicket/GitBlitWebSession.java create mode 100644 src/com/gitblit/wicket/LinkPanel.html create mode 100644 src/com/gitblit/wicket/LinkPanel.java create mode 100644 src/com/gitblit/wicket/RepositoryPage.java create mode 100644 src/com/gitblit/wicket/SecuredPage.java create mode 100644 src/com/gitblit/wicket/WicketUtils.java create mode 100644 src/com/gitblit/wicket/models/PathModel.java create mode 100644 src/com/gitblit/wicket/models/RefModel.java create mode 100644 src/com/gitblit/wicket/models/RepositoryModel.java create mode 100644 src/com/gitblit/wicket/pages/BlobPage.html create mode 100644 src/com/gitblit/wicket/pages/BlobPage.java create mode 100644 src/com/gitblit/wicket/pages/CommitPage.html create mode 100644 src/com/gitblit/wicket/pages/CommitPage.java create mode 100644 src/com/gitblit/wicket/pages/HeadsPage.html create mode 100644 src/com/gitblit/wicket/pages/HeadsPage.java create mode 100644 src/com/gitblit/wicket/pages/LogPage.html create mode 100644 src/com/gitblit/wicket/pages/LogPage.java create mode 100644 src/com/gitblit/wicket/pages/RepositoriesPage.html create mode 100644 src/com/gitblit/wicket/pages/RepositoriesPage.java create mode 100644 src/com/gitblit/wicket/pages/ShortLogPage.html create mode 100644 src/com/gitblit/wicket/pages/ShortLogPage.java create mode 100644 src/com/gitblit/wicket/pages/SummaryPage.html create mode 100644 src/com/gitblit/wicket/pages/SummaryPage.java create mode 100644 src/com/gitblit/wicket/pages/TagPage.html create mode 100644 src/com/gitblit/wicket/pages/TagPage.java create mode 100644 src/com/gitblit/wicket/pages/TagsPage.html create mode 100644 src/com/gitblit/wicket/pages/TagsPage.java create mode 100644 src/com/gitblit/wicket/pages/TreePage.html create mode 100644 src/com/gitblit/wicket/pages/TreePage.java create mode 100644 src/com/gitblit/wicket/panels/HeadLinksPanel.html create mode 100644 src/com/gitblit/wicket/panels/HeadLinksPanel.java create mode 100644 src/com/gitblit/wicket/panels/PageFooter.html create mode 100644 src/com/gitblit/wicket/panels/PageFooter.java create mode 100644 src/com/gitblit/wicket/panels/PageHeader.html create mode 100644 src/com/gitblit/wicket/panels/PageHeader.java create mode 100644 src/com/gitblit/wicket/panels/PageLinksPanel.html create mode 100644 src/com/gitblit/wicket/panels/PageLinksPanel.java create mode 100644 src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.html create mode 100644 src/com/gitblit/wicket/panels/PathBreadcrumbsPanel.java create mode 100644 src/com/gitblit/wicket/panels/PathLinksPanel.html create mode 100644 src/com/gitblit/wicket/panels/PathLinksPanel.java create mode 100644 src/com/gitblit/wicket/panels/RefsPanel.html create mode 100644 src/com/gitblit/wicket/panels/RefsPanel.java create mode 100644 src/com/gitblit/wicket/panels/ShortLogLinksPanel.html create mode 100644 src/com/gitblit/wicket/panels/ShortLogLinksPanel.java create mode 100644 src/com/gitblit/wicket/panels/TagLinksPanel.html create mode 100644 src/com/gitblit/wicket/panels/TagLinksPanel.java create mode 100644 src/com/gitblit/wicket/panels/TreeLinksPanel.html create mode 100644 src/com/gitblit/wicket/panels/TreeLinksPanel.java (limited to 'src/com/gitblit') 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 connectors = new ArrayList(); + 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 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 jars = new ArrayList(); + 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 findJars(File folder) { + List jars = new ArrayList(); + 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 getAllKeys(String startingWith) { + startingWith = startingWith.toLowerCase(); + List keys = new ArrayList(); + 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 getStrings(String name) { + return getStrings(name, " "); + } + + public static List getStringsFromValue(String value) { + return getStringsFromValue(value, " "); + } + + public static List getStrings(String name, String separator) { + List strings = new ArrayList(); + Properties props = read(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + strings = getStringsFromValue(value, separator); + } + return strings; + } + + public static List getStringsFromValue(String value, String separator) { + List strings = new ArrayList(); + 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 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 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 getRepositoryList(File repositoriesFolder, boolean exportAll, boolean readNested) { + List list = new ArrayList(); + list.addAll(getNestedRepositories(repositoriesFolder, repositoriesFolder, exportAll, readNested)); + Collections.sort(list); + return list; + } + + public static List getNestedRepositories(File repositoriesFolder, File folder, boolean exportAll, boolean readNested) { + String basefile = repositoriesFolder.getAbsolutePath(); + List list = new ArrayList(); + 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> getAllRefs(Repository r) { + Map> refs = new HashMap>(); + Map> allRefs = r.getAllRefsByPeeledObjectId(); + for (AnyObjectId id : allRefs.keySet()) { + List list = new ArrayList(); + for (Ref setRef : allRefs.get(id)) { + String name = setRef.getName(); + list.add(name); + } + refs.put(id.toObjectId(), list); + } + return refs; + } + + public static Map> getRefs(Repository r, String baseRef) { + Map> refs = new HashMap>(); + Map> allRefs = r.getAllRefsByPeeledObjectId(); + for (AnyObjectId id : allRefs.keySet()) { + List list = new ArrayList(); + 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 getFilesInPath(Repository r, String basePath, String commitId) { + RevCommit commit = getCommit(r, commitId); + return getFilesInPath(r, basePath, commit); + } + + public static List getFilesInPath(Repository r, String basePath, RevCommit commit) { + List list = new ArrayList(); + 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 getCommitChangedPaths(Repository r, String commitId) { + RevCommit commit = getCommit(r, commitId); + return getCommitChangedPaths(r, commit); + } + + public static List getCommitChangedPaths(Repository r, RevCommit commit) { + List list = new ArrayList(); + 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 getRevLog(Repository r, int maxCount) { + List list = new ArrayList(); + try { + Git git = new Git(r); + Iterable 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 getTags(Repository r, int maxCount) { + return getRefs(r, Constants.R_TAGS, maxCount); + } + + public static List getHeads(Repository r, int maxCount) { + return getRefs(r, Constants.R_HEADS, maxCount); + } + + public static List getRefs(Repository r, String refs, int maxCount) { + List list = new ArrayList(); + try { + Map 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 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 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 getRepositoryList() { + return JGitUtils.getRepositoryList(repositories, exportAll, StoredSettings.getBoolean("nestedRepositories", true)); + } + + public List getRepositories(Request request) { + List list = getRepositoryList(); + ServletWebRequest servletWebRequest = (ServletWebRequest) request; + HttpServletRequest req = servletWebRequest.getHttpServletRequest(); + + List repositories = new ArrayList(); + 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 @@ + + + +link + + \ 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 labelModel = new Model(); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public LinkPanel(String wicketId, final String linkCssClass, String label, Class 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() { + 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 map = new HashMap(); + // 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 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() { + private static final long serialVersionUID = 1L; + + @Override + public String getObject() { + return value; + } + }); + } + + public static String breakLines(String string) { + return string.replace("\r", "
").replace("\n", "
"); + } +} 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 { + + 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 { + + 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 @@ + + + + + + + + +
+ + +
+ + + + + +
+ + +
+ + +

+	
+	
+	
+ + \ 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 map = new HashMap(); + 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 @@ + + + + +
+ + +
+ + + + + +
+ + +
+ + +
+ + + + + + + + +
authorMessage goes here
Message goes here
committerMessage goes here
Message goes here
commitMessage goes here
treeMessage goes here
parent +
Message goes here
+
+ + +
+ + +
+ + + + + + +
+ + +
+ + \ 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 parents = new ArrayList(); + 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 parentsDp = new ListDataProvider(parents); + DataView parentsView = new DataView("commitParents", parentsDp) { + private static final long serialVersionUID = 1L; + + public void populateItem(final Item 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 paths = JGitUtils.getCommitChangedPaths(r, c); + ListDataProvider pathsDp = new ListDataProvider(paths); + DataView pathsView = new DataView("changedPath", pathsDp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 @@ + + + + +
+ + +
+ + +
+ + + + + + + + + +
+ + +
+ + \ 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 tags = JGitUtils.getHeads(r, -1); + r.close(); + + // shortlog + add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter())); + + ListDataProvider tagsDp = new ListDataProvider(tags); + DataView tagView = new DataView("head", tagsDp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 @@ + + + + +
+ + +
+ + +
+ + +
+
+ + +
+
+
+ + + +
+
+
+ +
+ + +
+ + \ 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> allRefs = JGitUtils.getAllRefs(r); + List commits = JGitUtils.getRevLog(r, 100); + r.close(); + + add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter())); + + // log + ListDataProvider dp = new ListDataProvider(commits); + DataView logView = new DataView("commit", dp) { + private static final long serialVersionUID = 1L; + + public void populateItem(final Item 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 @@ + + + +
+
+ + + + + + + + + + + + + + + + + + +
RepositoryDescriptionOwnerLast Change
+ + +
+ + \ 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 rows = GitBlitWebApp.get().getRepositories(getRequest()); + DataProvider dp = new DataProvider(rows); + DataView dataView = new DataView("repository", dp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 { + private static final long serialVersionUID = 1L; + private List list = null; + + protected DataProvider(List list) { + this.list = list; + setSort(SortBy.date.name(), false); + } + + @Override + public int size() { + if (list == null) + return 0; + return list.size(); + } + + @Override + public IModel model(RepositoryModel header) { + return new Model(header); + } + + @Override + public Iterator 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() { + @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() { + @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() { + @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() { + @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 @@ + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + +
+ + +
+ + \ 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> allRefs = JGitUtils.getAllRefs(r); + List commits = JGitUtils.getRevLog(r, 100); + r.close(); + + // shortlog + add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter())); + + ListDataProvider dp = new ListDataProvider(commits); + DataView shortlogView = new DataView("commit", dp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 @@ + + + + +
+ + +
+ + +
 
+ + + + + +
descriptionMessage goes here
ownerMessage goes here
last changeMessage goes here
+ + + +
+ + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + +
+ + + +
+ + \ 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> 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 commits = JGitUtils.getRevLog(r, summaryCount); + ListDataProvider dp = new ListDataProvider(commits); + DataView shortlogView = new DataView("commit", dp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 tags = JGitUtils.getTags(r, summaryCount); + add(new LinkPanel("tags", "title", "tags", TagsPage.class, newRepositoryParameter())); + + ListDataProvider tagsDp = new ListDataProvider(tags); + DataView tagView = new DataView("tag", tagsDp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 heads = JGitUtils.getHeads(r, summaryCount); + add(new LinkPanel("heads", "title", "heads", HeadsPage.class, newRepositoryParameter())); + + ListDataProvider headsDp = new ListDataProvider(heads); + DataView headsView = new DataView("head", headsDp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 @@ + + + + +
+ + +
+ + +
+ + +
+ + + + +
objectMessage goes here
authorMessage goes here
Message goes here
+
+ + +
+ + +
+ + \ 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 @@ + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + +
+ + +
+ + \ 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 tags = JGitUtils.getTags(r, -1); + r.close(); + + // shortlog + add(new LinkPanel("summary", "title", repositoryName, SummaryPage.class, newRepositoryParameter())); + + ListDataProvider tagsDp = new ListDataProvider(tags); + DataView tagView = new DataView("tag", tagsDp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 @@ + + + + +
+ + +
+ + + + + +
+ + +
+ + +
+ + + + + + + +
+ + +
+ + \ 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 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 pathsDp = new ListDataProvider(paths); + DataView pathsView = new DataView("changedPath", pathsDp) { + private static final long serialVersionUID = 1L; + int counter = 0; + + public void populateItem(final Item 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 @@ + + + + + + \ 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 @@ + + + + + + \ 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 @@ + + + + + Message goes here + + + + + + + + \ 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 @@ + + + + + + + \ 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 @@ + + + + +
+ + + +
+
+ \ 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 crumbs = new ArrayList(); + 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 crumbsDp = new ListDataProvider(crumbs); + DataView pathsView = new DataView("path", crumbsDp) { + private static final long serialVersionUID = 1L; + + public void populateItem(final Item 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 @@ + + + + + + \ 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 @@ + + + + + ref + + + \ 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> refs) { + super(id); + List refNames = refs.get(c.getId()); + if (refNames == null) { + refNames = new ArrayList(); + } + Collections.sort(refNames); + ListDataProvider refsDp = new ListDataProvider(refNames); + DataView refsView = new DataView("ref", refsDp) { + private static final long serialVersionUID = 1L; + public void populateItem(final Item 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 @@ + + + + + + \ 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 @@ + + + + + + \ 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 @@ + + + + + + \ 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 -- cgit v1.2.3