diff --git a/.gitignore b/.gitignore index e268ccbc1..c02c62637 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ tags +\#*\# /temp /lib /ext @@ -30,3 +31,10 @@ tags /**/init.lua /**/session /nbproject/private +# backup files from most of editors +*.java~ +*.html~ +*.properties~ +*.xml~ +# Generated javadoc files for "javadoc" target. +/javadoc diff --git a/build.moxie b/build.moxie index f970c3a25..fe7cf446b 100644 --- a/build.moxie +++ b/build.moxie @@ -10,7 +10,7 @@ name: Gitblit description: pure Java Git solution groupId: com.gitblit artifactId: gitblit -version: 1.9.2-SNAPSHOT +version: 1.9.2-TomaszSzt.1.01 inceptionYear: 2011 # Current stable release diff --git a/build.xml b/build.xml index afe604969..65bc9c73c 100644 --- a/build.xml +++ b/build.xml @@ -1,6 +1,17 @@ - + - + + @@ -37,6 +49,11 @@ + + + + + JDK version: ${ant.java.version} - - - + Calling compiler to show version: + + + Java/JVM version: ${java.version} @@ -133,7 +151,8 @@ - + @@ -1085,7 +1104,8 @@ GB_RELEASE_TAG=${project.tag} - + + @@ -1296,4 +1316,33 @@ GB_RELEASE_TAG=${project.tag} + + + + + + + + + + + diff --git a/empty.java b/empty.java new file mode 100644 index 000000000..4da23b15c --- /dev/null +++ b/empty.java @@ -0,0 +1,4 @@ +/* + Nothing. Just to force ANT compiler to show version. + See build.xml "prepare" target. +*/ \ No newline at end of file diff --git a/setEnv.bat b/setEnv.bat new file mode 100644 index 000000000..dac01d3f1 --- /dev/null +++ b/setEnv.bat @@ -0,0 +1,37 @@ +@rem A mininum environmental set-up to allow console to +@rem run different ANT and different JDK than rest of the build system. +@rem Run this batch script ONCE per console. + +@rem Prequisites: +@rem - JDK 7 needs to be used to compile and provide class files. +@rem - either ANT 1.9 line needs to be used to handle compilation +@rem when JRE from JDK 7 is to be used or +@rem - java must be pointed out directly to version which is compatible +@rem with Your ANT system. + +@echo Seting up path to java jdk home folder +@SET JAVA_HOME=c:\jdk1.7.0_80 + +@echo Seting up path to java.exe in JRE home folder +@SET JAVACMD=c:\jdk8\jre\bin\java.exe + +@echo Removing old ANT path from +@set PATH=%PATH:C:\ant\bin=% + +@echo Adding new ANT path +@set PATH=c:\ant\bin;%PATH% + +@echo -------------------------- +@echo JAVA_HOME is "%JAVA_HOME%" +@echo -------------------------- +@echo PATH is "%PATH%" +@echo -------------------------- +@echo JRE version which will be running all non-ANT jobs is: +@java -version +@echo -------------------------- +@echo JRE version which will be running ANT is: +@%JAVACMD% -version +@echo -------------------------- +@echo Check if JRE version is at least 7.171, 8.161, or 9.148 +@echo Otherwise You may expect some SSL exceptions when scripts will +@echo attempt to connect to github to fetch dependencies. \ No newline at end of file diff --git a/src/main/distrib/data/defaults.properties b/src/main/distrib/data/defaults.properties index 5dea6a0a4..d11377bbd 100644 --- a/src/main/distrib/data/defaults.properties +++ b/src/main/distrib/data/defaults.properties @@ -1484,9 +1484,29 @@ web.binaryExtensions = 7z arc arj bin dll doc docx exe gz jar lib lzh odg odf od # SINCE 0.5.0 web.aggressiveHeapManagement = false -# Run the webapp in debug mode +# Run the webapp in debug mode. +# Allowed values are: +# false - INFO reporting level +# true - DEBUG reporting level # -# SINCE 0.5.0 +# If more precise tuning is necessary ${baseFolder}/log4j.properties file +# should be used to override default settings AND this value should be left +# as "false". +# +# To enable full detailed logging create ${baseFolder}/log4j.properties text file +# with a single line: +# +# log4j.rootLogger=ALL, S +# +# to debug to console or start server with --dailyLogFile to redirect +# logging to "${baseFolder}/log/gitblit.log" file. +# +# Alternatively a more readable debug level can be achived by: +# +# log4j.rootLogger=INFO, S +# log4j.logger.com.gitblit=ALL +# +# SINCE 1.9.2 # RESTART REQUIRED web.debugMode = false @@ -1532,6 +1552,15 @@ web.maxDiffLinesPerFile = 4000 # SINCE 1.7.0 web.maxDiffLines = 20000 +# Maximum number of changed files in single commit to process and display +# on commit page. Set to -1 to disable limit. +# +# Keeping this limit at -1 may cause lags and memory overloads if huge +# commits with many files are present in system. +# +# SINCE 1.9.2 +web.maxCommitPaths=-1 + # Enable/disable global regex substitutions (i.e. shared across repositories) # # SINCE 0.5.0 diff --git a/src/main/distrib/data/log4j-debug-example.properties b/src/main/distrib/data/log4j-debug-example.properties new file mode 100644 index 000000000..1a60c4354 --- /dev/null +++ b/src/main/distrib/data/log4j-debug-example.properties @@ -0,0 +1,59 @@ +# +# In this example we show how to override +# debugging settings to provide detailed information +# about what and where have happen in GIT blit +# +# Settings made with this file do CONFLICT with --dailyLogFile command line +# and web.debugMode option overriding their effects. +# +# To activate this example rename it to "log4j.properties" +# and restart server. +# + +# +# In below example we are saying that globally we are interested +# in messages on the level INFO and are going to output it to +# console. +# +# If output to a file is expected use: +# +# log4j.rootLogger=INFO, R +# +# Note: The --dailyLogFile server command line parameter is an +# another option to output to a file, but +# we should not use it with conjunction with this settings. +# +# Other levels You may use are ERROR,WARN,INFO,DEBUG,ALL, from most important +# (ERROR) to less (ALL). +# +log4j.rootLogger=INFO, S + +# +# In this line we are telling that all JAVA classes which come from +# any com.gitblit.* package should report everything they can do. +# +log4j.logger.com.gitblit=ALL +# +# Now, since we are doing a bug hunt we do enable +# full blow formatting which will tell us not only a message, but also where +# exactly it was made in code. Notice, this hurts performance. + +# +# Below line ensures, that specified layout is used for file storage +# +log4j.appender.R.layout = org.apache.log4j.PatternLayout +# +# And what exactly the layout is. The %d means the date of message, +# with up to 1ms accuracy. +# The %l means source information +# %p means priority (the -5) means "left pad with spaces up to 5 chars long +# %m means "message" +# %n means "end of line" +# +log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} [%-5p] %n %l %n %m%n + +# +# We do repeat it for console output. +# +log4j.appender.S.layout = org.apache.log4j.PatternLayout +log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %l [%-5p] %n %l %n %m%n \ No newline at end of file diff --git a/src/main/java/com/gitblit/GitBlitServer.java b/src/main/java/com/gitblit/GitBlitServer.java index 06000f531..0250d5d33 100644 --- a/src/main/java/com/gitblit/GitBlitServer.java +++ b/src/main/java/com/gitblit/GitBlitServer.java @@ -73,7 +73,7 @@ /** * GitBlitServer is the embedded Jetty server for Gitblit GO. This class starts * and stops an instance of Jetty that is configured from a combination of the - * gitblit.properties file and command line parameters. JCommander is used to + * gitblit.properties file and command line parameters. Args4j is used to * simplify command line parameter processing. This class also automatically * generates a self-signed certificate for localhost, if the keystore does not * already exist. @@ -83,11 +83,22 @@ */ public class GitBlitServer { + private static Logger logger; - + public static void main(String... args) { - GitBlitServer server = new GitBlitServer(); - + main(GitBlitServer.class, args); + } + /** + A main method which is declated in such a way, that + exactly the same per-processing of parameters can + be used in subclasses which are designed for testing + purposes. + + @see de.akquinet.devops.GitBlitServer4UITests + */ + protected static void main( Class impl, String... args) + { // filter out the baseFolder parameter List filtered = new ArrayList(); String folder = "data"; @@ -105,25 +116,50 @@ public static void main(String... args) { filtered.add(arg); } } - + //parse parameters Params.baseFolder = folder; Params params = new Params(); CmdLineParser parser = new CmdLineParser(params); try { parser.parseArgument(filtered); if (params.help) { - server.usage(parser, null); + usage(parser, null); } } catch (CmdLineException t) { - server.usage(parser, t); + usage(parser, t); } - + + if (params.stop) { - server.stop(params); + stop(params); } else { - server.start(params); + //Set up log services BEFORE any class which may use logs is touched. + //The logging system initialization in classes along this application + // uses mixed policy: + // static final Logger logger =... + // or dynamic, per instance + // final Logger logger = .... + // So we need to configure logging as quickly as possible so that + // class loaders would not create misconfigured loggers. + + //Load file settings, since pieces of them do configure logging. + FileSettings settings = params.FILESETTINGS; + if (!StringUtils.isEmpty(params.settingsfile)) { + if (new File(params.settingsfile).exists()) { + settings = new FileSettings(params.settingsfile); + } + } + //Set up logging. + setUpLogging(settings, params); + try{ + GitBlitServer server = impl.newInstance(); + server.start(params, settings); + }catch(InstantiationException ex){ throw new RuntimeException(ex); } + catch(IllegalAccessException ex){ throw new RuntimeException(ex); } } - } + }; + + /** * Display the command line usage of Gitblit GO. @@ -131,7 +167,7 @@ public static void main(String... args) { * @param parser * @param t */ - protected final void usage(CmdLineParser parser, CmdLineException t) { + protected final static void usage(CmdLineParser parser, CmdLineException t) { System.out.println(Constants.BORDER); System.out.println(Constants.getGitBlitVersion()); System.out.println(Constants.BORDER); @@ -148,7 +184,7 @@ protected final void usage(CmdLineParser parser, CmdLineException t) { System.exit(0); } - protected File getBaseFolder(Params params) { + protected static File getBaseFolder(Params params) { String path = System.getProperty("GITBLIT_HOME", Params.baseFolder); if (!StringUtils.isEmpty(System.getenv("GITBLIT_HOME"))) { path = System.getenv("GITBLIT_HOME"); @@ -160,7 +196,7 @@ protected File getBaseFolder(Params params) { /** * Stop Gitblt GO. */ - public void stop(Params params) { + public static void stop(Params params) { try { Socket s = new Socket(InetAddress.getByName("127.0.0.1"), params.shutdownPort); OutputStream out = s.getOutputStream(); @@ -177,45 +213,12 @@ public void stop(Params params) { /** * Start Gitblit GO. + @param params command line parameters, parsed + @param settings loaded settings from properties fiels. */ - protected final void start(Params params) { + protected final void start(Params params, FileSettings settings) { final File baseFolder = getBaseFolder(params); - FileSettings settings = params.FILESETTINGS; - if (!StringUtils.isEmpty(params.settingsfile)) { - if (new File(params.settingsfile).exists()) { - settings = new FileSettings(params.settingsfile); - } - } - - if (params.dailyLogFile) { - // Configure log4j for daily log file generation - InputStream is = null; - try { - is = getClass().getResourceAsStream("/log4j.properties"); - Properties loggingProperties = new Properties(); - loggingProperties.load(is); - - loggingProperties.put("log4j.appender.R.File", new File(baseFolder, "logs/gitblit.log").getAbsolutePath()); - loggingProperties.put("log4j.rootCategory", "INFO, R"); - - if (settings.getBoolean(Keys.web.debugMode, false)) { - loggingProperties.put("log4j.logger.com.gitblit", "DEBUG"); - } - - PropertyConfigurator.configure(loggingProperties); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (is != null) { - is.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - + logger = LoggerFactory.getLogger(GitBlitServer.class); logger.info("\n" + Constants.getASCIIArt()); @@ -224,7 +227,7 @@ protected final void start(Params params) { String osname = System.getProperty("os.name"); String osversion = System.getProperty("os.version"); logger.info("Running on " + osname + " (" + osversion + ")"); - + String javaversion = System.getProperty("java.version"); String javavendor = System.getProperty("java.vendor"); logger.info("JVM version " + javaversion + " (" + javavendor + ")"); @@ -482,7 +485,179 @@ protected GitblitContext newGitblit(IStoredSettings settings, File baseFolder) { private boolean isWindows() { return System.getProperty("os.name").toLowerCase().indexOf("windows") > -1; } - + + /** + A routine responsible for setting up log4j/slf4j logging + environment. This method should be called inside {@link #start} + before {@link #logger} is initialized. +

+ If {@link #logger} is already initialized this method does not do + anything. +

+ This method is using data stored in: +

+ All errors are printed to System.err and ignored. + If any override of jar /log4j.properties is applied + apropriate informations are printed to System.out. + @param settings content of "default.properties" file and/or it's overrides. + @param params parsed command-line parameters + */ + private static void setUpLogging(final FileSettings settings, final Params params) + { + final File baseFolder = getBaseFolder(params); + //Note: + // The loging set-up is using quite a tricky dependency + // since slf4j (in pre 2.0 on which GitBlit depends) is + // relying on presence of some specific implementation classes on a class path. + // + // This type of dependency results in invisible in code + // but totally transparent logging engine selection. + // The presence of slf4j "slf4j-log4j12-xxx.jar" sets up + // what type of loging service will be in use. + // + // This makes however tricky to validate what setting is really used. + // Gitblit devs assumed that log4j is used, so we need to validate it. + // + assert(LoggerFactory.getILoggerFactory() instanceof org.slf4j.impl.Log4jLoggerFactory): + "Runtime environment is not configured correctly for log4j use"; + + // Originally GITBlit assumed, that debug level configuration is possible + // with "web.debugMode" option in "data/default.properties" only if server is run + // with --dailyLogFile parameter what, effectively, confused users which were running + // it with log to console. + + //Since we know we are using log4j we can configure it from a "hidden" file + //This file is by default in "gitblit.jar" what makes it problematic for user + //to load. Thous we will first load it from that file and THEN make an attempt + //to override/append data by loading from a baseFolder/log4j.properties + + Properties loggingProperties = new Properties(); //<--- log4j configuration will be here. + //Internally stored settings. + { + InputStream is = null; + try{ + is = GitBlitServer.class.getResourceAsStream("/log4j.properties"); + assert(is!=null); //this resource is always present. + loggingProperties.load(is); + }catch (Exception e) + { + e.printStackTrace(); + System.err.println("Could not set up logging services. Logging services are running in default mode."); + return; //Nothing else to do + }finally + { + try{ + if (is != null) is.close(); + } catch (IOException e) { + e.printStackTrace(); + //This exception should not prevent us from continouing. + } + } + }; + //Now pick up default setting so we could later detect if user have overriden it. + //Both defaults cannot be null. Since this is an internal file assertions are fine. + final String default_gitblit_level = loggingProperties.getProperty("log4j.logger.com.gitblit"); + assert(default_gitblit_level!=null):"invalid content of jar stored log4j.properties file, missing log4j.logger.com.gitblit"; + final String default_root_level = loggingProperties.getProperty("log4j.rootLogger"); + assert(default_root_level!=null):"invalid content of jar stored log4j.properties file, missing log4j.rootLogger"; + final String default_log_file = loggingProperties.getProperty("log4j.appender.R.File"); + assert(default_log_file!=null):"invalid content of jar stored log4j.properties file, missing log4j.appender.R.File"; + + //Load overrides from file + boolean display_logging_configuration = false; //<-- this variable will keep track if any override is + //applied so we can later show overrides to user. + { + final File f = new File(params.baseFolder+"/log4j.properties"); + if (f.exists()) + { + display_logging_configuration=true; + System.out.println("Using "+f+" to override logging configuration."); + InputStream is = null; + try{ + try{ + is = new java.io.FileInputStream(f); + loggingProperties.load(is); + }catch(Exception e) + { + System.err.println("Failed to load user defined logging settings due to "+e); + e.printStackTrace(); + //this does not stop us from continuing. + }; + }finally{ + try{ + if (is!=null) is.close(); + }catch(IOException ex){ ex.printStackTrace(); }; //<-- again we can continue + }; + }; + }; + //Now apply overrides to level controlled by web.debugMode option. + //These overrides are applied ONLY if default level setting were not overriden + //by custom log4j.properties file. + if (settings.getBoolean(Keys.web.debugMode, false)) + { + display_logging_configuration=true; + System.out.println("Using web.debugMode to override debug levels."); + if (default_gitblit_level.equals(loggingProperties.getProperty("log4j.logger.com.gitblit"))) + { + loggingProperties.setProperty("log4j.logger.com.gitblit", "DEBUG"); + }else + System.out.println("web.debugMode requested, but ignored due to log4j.properties file was used to override log4j.logger.com.gitblit setup"); + if (default_root_level.equals(loggingProperties.getProperty("log4j.rootLogger"))) + { + //Now the override needs to be partial only, + int i = default_root_level.indexOf(','); + assert(i!=-1):"internal log4j.properties log4j.rootLogger="+default_root_level+", missing default appender."; + loggingProperties.setProperty("log4j.rootLogger", "DEBUG"+default_root_level.substring(i)); + }else + System.out.println("web.debugMode requested, but ignored due to log4j.properties file was used to override log4j.rootLogger setup"); + } + //Decide of daily file overrides. Basically we can override appender file and the appender itself. + if (params.dailyLogFile) + { + display_logging_configuration=true; + System.out.println("Using --dailyLogFile to override log output."); + //We start from validating if appender selection is default. + if (default_root_level.equals(loggingProperties.getProperty("log4j.rootLogger"))) + { + int i = default_root_level.indexOf(','); + assert(i!=-1):"internal log4j.properties log4j.rootLogger="+default_root_level+", missing default appender."; + loggingProperties.setProperty("log4j.rootLogger", default_root_level.substring(0,i)+",R"); + }else + System.out.println("--dailyLogFile requested, but ignored due to log4j.properties file was used to override log4j.rootLogger setup"); + //And now check if we can replace a target file. + if (default_log_file.equals(loggingProperties.get("log4j.appender.R.File"))) + { + //yes, it does, we can override it + loggingProperties.setProperty("log4j.appender.R.File", new File(baseFolder, default_log_file).getAbsolutePath()); + }else + System.out.println("--dailyLogFile requested, but ignored due to log4j.properties file was used to override log4j.appender.R.File setup"); + }; + //All overrides are applied. If any overrides were requested we need to show them since due to multiple + //ways of defining configurations it may be tricky. + if (display_logging_configuration) + { + System.out.println("Combined logging setup data are:"); + for(Object S:loggingProperties.keySet()) + { + System.out.println("\t"+S+"="+loggingProperties.get(S)); + }; + }; + //Now apply them to log4j. + try{ + PropertyConfigurator.configure(loggingProperties); + }catch(Exception ex) + { + System.err.println("Failed to apply log4j configuration due to "+ex); + ex.printStackTrace(); + }; + }; /** * The ShutdownMonitorThread opens a socket on a specified port and waits * for an incoming connection. When that connection is accepted a shutdown diff --git a/src/main/java/com/gitblit/utils/JGitUtils.java b/src/main/java/com/gitblit/utils/JGitUtils.java index e70b4f996..3e80ef58d 100644 --- a/src/main/java/com/gitblit/utils/JGitUtils.java +++ b/src/main/java/com/gitblit/utils/JGitUtils.java @@ -123,7 +123,8 @@ public class JGitUtils { static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class); - + static final boolean TRACE = LOGGER.isTraceEnabled(); + static final boolean DEBUG = LOGGER.isDebugEnabled(); /** * Log an error message and exception. * @@ -997,9 +998,29 @@ public static List getFilesInCommit(Repository repository, RevC * if true, each PathChangeModel will have insertions/deletions * @return list of files changed in a commit */ - public static List getFilesInCommit(Repository repository, RevCommit commit, boolean calculateDiffStat) { + public static List getFilesInCommit(Repository repository, RevCommit commit, boolean calculateDiffStat) + { + return getFilesInCommit(repository,commit,calculateDiffStat,-1); + }; + /** + * Returns the list of files changed in a specified commit. If the + * repository does not exist or is empty, an empty list is returned. + * + * @param repository + * @param commit + * if null, HEAD is assumed. + * @param calculateDiffStat + * if true, each PathChangeModel will have insertions/deletions + @param files_limit maximum number of files to process. If there are more files + in commit remaning files are ignored. -1 to disable this limit + * @return list of files changed in a commit. This list will be up to files_limit in size. + */ + public static List getFilesInCommit(Repository repository, RevCommit commit, boolean calculateDiffStat, int files_limit) { + if (TRACE) LOGGER.trace("computing changed files in commit "+commit+" repository "+repository+" with calculateDiffStat="+calculateDiffStat+" files_limit="+files_limit); + assert((files_limit>=0)||(files_limit==-1)); List list = new ArrayList(); if (!hasCommits(repository)) { + if (TRACE) LOGGER.trace("No commits."); return list; } RevWalk rw = new RevWalk(repository); @@ -1010,6 +1031,8 @@ public static List getFilesInCommit(Repository repository, RevC } if (commit.getParentCount() == 0) { + if (TRACE) LOGGER.trace("Commit has no parent, faking diffs."); + int counted_files = 0; TreeWalk tw = new TreeWalk(repository); tw.reset(); tw.setRecursive(true); @@ -1035,15 +1058,24 @@ public static List getFilesInCommit(Repository repository, RevC list.add(new PathChangeModel(tw.getPathString(), tw.getPathString(),filestoreItem, size, tw .getRawMode(0), objectId.getName(), commit.getId().getName(), ChangeType.ADD)); + counted_files++; + if (TRACE) LOGGER.trace("Processed "+counted_files+" commit files"); + if ((files_limit>=0) && (counted_files>=files_limit)) + { + if (TRACE) LOGGER.trace("too many files, stopping computations"); + break; + }; } tw.close(); } else { + if (TRACE) LOGGER.trace("Commit has parent some parent, computing diffs"); RevCommit parent = rw.parseCommit(commit.getParent(0).getId()); DiffStatFormatter df = new DiffStatFormatter(commit.getName(), repository); df.setRepository(repository); df.setDiffComparator(RawTextComparator.DEFAULT); df.setDetectRenames(true); List diffs = df.scan(parent.getTree(), commit.getTree()); + int counted_files=0; for (DiffEntry diff : diffs) { // create the path change model PathChangeModel pcm = PathChangeModel.from(diff, commit.getName(), repository); @@ -1058,6 +1090,13 @@ public static List getFilesInCommit(Repository repository, RevC } } list.add(pcm); + counted_files++; + if (TRACE) LOGGER.trace("Processed "+counted_files+" commit files"); + if ((files_limit>=0) && (counted_files>=files_limit)) + { + if (TRACE) LOGGER.trace("too many files, stopping computations"); + break; + }; } } } catch (Throwable t) { @@ -1065,6 +1104,7 @@ public static List getFilesInCommit(Repository repository, RevC } finally { rw.dispose(); } + if (TRACE) LOGGER.trace("Finished computing commit data"); return list; } @@ -2357,7 +2397,7 @@ public static boolean repairFetchSpecs(Repository repository) { try { rc.save(); rc.load(); - LOGGER.debug("repaired {} invalid fetch refspecs for {}", repairedSpecs, repository.getDirectory()); + if (DEBUG) LOGGER.debug("repaired {} invalid fetch refspecs for {}", repairedSpecs, repository.getDirectory()); return true; } catch (Exception e) { LOGGER.error(null, e); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index c10d88732..b306fefc2 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -190,8 +190,11 @@ public void init() { } // configure the resource cache duration to 90 days for deployment + // and enable resources to fall back to defaults if not found if (!isDebugMode()) { getResourceSettings().setDefaultCacheDuration(90 * 86400); + getResourceSettings().setUseDefaultOnMissingResource(true); + getResourceSettings().setThrowExceptionOnMissingResource(false); } // setup the standard gitweb-ish urls diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 9c643d926..662e789a7 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -64,6 +64,7 @@ gb.filesModified = {0} files modified gb.filesDeleted = {0} files deleted gb.filesCopied = {0} files copied gb.filesRenamed = {0} files renamed +gb.CommitLegendPanel.moreChanges= + more changes gb.missingUsername = Missing Username gb.edit = edit gb.searchTypeTooltip = Select Search Type @@ -504,7 +505,8 @@ gb.todaysActivityNone = today / none gb.noActivityToday = there has been no activity today gb.anonymousUser= anonymous gb.commitMessageRenderer = commit message renderer -gb.diffStat = {0} insertions & {1} deletions +gb.diffStat = {0} insertions & {1} deletions {2,choice,0#|1#or more} +gb.diffStat.total={0}{1,choice,0#|1# or more} gb.home = home gb.isMirror = this repository is a mirror gb.mirrorOf = mirror of {0} diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties index a4753e72f..40aab96ae 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties @@ -502,6 +502,8 @@ gb.todaysActivityStats = dzisiaj / {1} zmian przez {2} autor\u00F3w gb.todaysActivityNone = dzisiaj / brak gb.noActivityToday = brak aktywno\u015Bci w dniu dzisiejszym gb.anonymousUser= anonimowy +gb.diffStat = {0} wstawie\u0144 & {1} usuni\u0119\u0107 {2,choice,0#|1#lub wi\u0119cej} +gb.diffStat.total={0}{1,choice,0#|1# lub wi\u0119cej} # This last property for unit tests to test successful loading of the resource file gb.loadLang = polszczyzna diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java index 0d99f5e52..0a7258ee3 100644 --- a/src/main/java/com/gitblit/wicket/pages/BasePage.java +++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java @@ -69,10 +69,35 @@ import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; +/** + Wicket WebPage page providing common services + for GitBlit purposes. +*/ public abstract class BasePage extends SessionPage { - private transient Logger logger; - + /** Lazy initialized with {@link #logger} */ + private transient Logger logger; //Note: this field could be static final which would be + //possibly faster and better, but in such case loggers + //would be bound with BasePage.class and there would + //be no possibility to filter log data on per-class. + //It might be better (faster) but some code: + // private static final Logger logger = LoggerFactory.getLogger(x.class) + // private static final boolean TRACE = logger.isTraceEnabled(); + //should be copied into each class. I think, it would be better, but it is + //a matter of personal choice. + /** Keeps TRACE logging status. Set up in {@link #getLogger} + first call. Zero means "unknown", "1" disabled and "2" enabled */ + private transient byte is_Trace_Enabled; + /** See {@link #is_Trace_Enabled} */ + private transient byte is_Debug_Enabled; + /** See {@link #is_Trace_Enabled} */ + private transient byte is_Info_Enabled; + /** See {@link #is_Trace_Enabled} */ + private transient byte is_Warn_Enabled; + /** See {@link #is_Trace_Enabled} */ + private transient byte is_Error_Enabled; + + /** Lazy initialized with {@link #getTimeUtils} */ private transient TimeUtils timeUtils; public BasePage() { @@ -85,12 +110,141 @@ public BasePage(PageParameters params) { customizeHeader(); } + /** + Returns logger associated with this.getClass() + If logger is not already present it creates it at first invocation. +

+ Notes about logging performance. +

+ Use below pattern for WARN and ERROR levels. +

+			logger().warn("message");
+			logger().error("message");
+		
+

+ Logging at level WARN or ERROR is usually rare and even a costly + process of formulating text does not impact performance. + Logging at levels TRACE, DEBUG, and INFO are few order of magnitudes + denser and especially trace may harm performance. +

+ To maximize the performance creation of log message must be avoided + if log level is not enabled. User may use: +

+			if (logger().isTraceEnabled()) logger().trace("xxx");
+		
+ but this will cost at least a sequence of 5 interface calls which + are not very fast. +

+ To avoid this burden and ecourage users to use extensive logging + this class is providing own {@link #isTraceEnabled}, + {@link #isDebugEnabled}, {@link #isInfoEnabled}, {@link #isWarnEnabled}, + {@link #isErrorEnabled} methods which are effectively a single field read. +

+ Following pattern is recommended: +

+			if (isTraceEnable()) logger().trace(complex message);
+		
+ + @return a logger instance. The underlying library is not specifiying + if it may return null or not, but at least one of underlying + implementations is said to never return a null. Life time constant. + */ protected Logger logger() { if (logger == null) { logger = LoggerFactory.getLogger(getClass()); + assert(logger!=null); + is_Trace_Enabled = logger.isTraceEnabled() ? (byte)2 : (byte)1; + is_Debug_Enabled = logger.isDebugEnabled() ? (byte)2 : (byte)1; + is_Info_Enabled = logger.isInfoEnabled() ? (byte)2 : (byte)1; + is_Warn_Enabled = logger.isWarnEnabled() ? (byte)2 : (byte)1; + is_Error_Enabled = logger.isErrorEnabled() ? (byte)2 : (byte)1; } return logger; } + /** A fastest possible test if TRACE logging is enabled + @return true if enable, false if not. Life time constant. + @see #logger + */ + protected final boolean isTraceEnabled() + { + switch(is_Trace_Enabled) + { + case 1: return false; + case 2: return true; + default: + logger(); + assert( (is_Trace_Enabled==1)||(is_Trace_Enabled==2)); + return isTraceEnabled(); + } + }; + + /** A fastest possible test if Debug logging is enabled + @return true if enable, false if not. Life time constant. + @see #logger + */ + protected final boolean isDebugEnabled() + { + switch(is_Debug_Enabled) + { + case 1: return false; + case 2: return true; + default: + logger(); + assert( (is_Debug_Enabled==1)||(is_Debug_Enabled==2)); + return isDebugEnabled(); + } + }; + + /** A fastest possible test if Info logging is enabled + @return true if enable, false if not. Life time constant. + @see #logger + */ + protected final boolean isInfoEnabled() + { + switch(is_Info_Enabled) + { + case 1: return false; + case 2: return true; + default: + logger(); + assert( (is_Info_Enabled==1)||(is_Info_Enabled==2)); + return isInfoEnabled(); + } + }; + + /** A fastest possible test if Warn logging is enabled + @return true if enable, false if not. Life time constant. + @see #logger + */ + protected final boolean isWarnEnabled() + { + switch(is_Warn_Enabled) + { + case 1: return false; + case 2: return true; + default: + logger(); + assert( (is_Warn_Enabled==1)||(is_Warn_Enabled==2)); + return isWarnEnabled(); + } + }; + + /** A fastest possible test if Error logging is enabled + @return true if enable, false if not. Life time constant. + @see #logger + */ + protected final boolean isErrorEnabled() + { + switch(is_Error_Enabled) + { + case 1: return false; + case 2: return true; + default: + logger(); + assert( (is_Error_Enabled==1)||(is_Error_Enabled==2)); + return isErrorEnabled(); + } + }; private void customizeHeader() { if (app().settings().getBoolean(Keys.web.useResponsiveLayout, true)) { diff --git a/src/main/java/com/gitblit/wicket/pages/BlamePage.java b/src/main/java/com/gitblit/wicket/pages/BlamePage.java index 2fcca0ae1..8465058f3 100644 --- a/src/main/java/com/gitblit/wicket/pages/BlamePage.java +++ b/src/main/java/com/gitblit/wicket/pages/BlamePage.java @@ -108,7 +108,7 @@ public BlamePage(PageParameters params) { if (pathModel == null) { final String notFound = MessageFormat.format("Blame page failed to find {0} in {1} @ {2}", blobPath, repositoryName, objectId); - logger.error(notFound); + logger().error(notFound); add(new Label("annotation").setVisible(false)); add(new Label("missingBlob", missingBlob(blobPath, commit)).setEscapeModelStrings(false)); return; diff --git a/src/main/java/com/gitblit/wicket/pages/CommitPage.java b/src/main/java/com/gitblit/wicket/pages/CommitPage.java index 3998204d1..2a214a233 100644 --- a/src/main/java/com/gitblit/wicket/pages/CommitPage.java +++ b/src/main/java/com/gitblit/wicket/pages/CommitPage.java @@ -36,6 +36,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; +import com.gitblit.Keys; import com.gitblit.Constants; import com.gitblit.models.GitNote; import com.gitblit.models.PathModel.PathChangeModel; @@ -58,11 +59,14 @@ @CacheControl(LastModified.BOOT) public class CommitPage extends RepositoryPage { + public CommitPage(PageParameters params) { super(params); Repository r = getRepository(); RevCommit c = getCommit(); + + if (isTraceEnabled()) logger().trace("Building commits page for:"+r+" commit "+c); List parents = new ArrayList(); if (c.getParentCount() > 0) { @@ -136,6 +140,7 @@ public void populateItem(final Item item) { @Override public void populateItem(final Item item) { + if (isTraceEnabled()) logger().trace("Polulating note item "+item.getModelObject()); GitNote entry = item.getModelObject(); item.add(new RefsPanel("refName", repositoryName, Arrays.asList(entry.notesRef))); item.add(createPersonPanel("authorName", entry.notesRef.getAuthorIdent(), @@ -150,8 +155,26 @@ public void populateItem(final Item item) { add(notesView.setVisible(notes.size() > 0)); // changed paths list - List paths = JGitUtils.getFilesInCommit(r, c); - + if (isTraceEnabled()) logger().trace("Loading changed paths"); + + final List paths; + final boolean commit_is_trimmed; + { + //pick up processing limit from server settings + int paths_limit = app().settings().getInteger(Keys.web.maxCommitPaths,-1); + if (!((paths_limit>=0)||(paths_limit==-1))) + { + logger().warn("web.maxCommitPaths is set to "+paths_limit+" what is not -1 or any positive number. Using -1 instead"); + paths_limit=-1; + }; + //compute with diffs. + paths = JGitUtils.getFilesInCommit(r, c, true,paths_limit); + //check if limit is touched. + //Yes, i know, there is a boundary case when EXACTLY limit files were in commit, but I do ignore it + //because otherwise getFilesInCommit API would have to be changed. + commit_is_trimmed = (paths.size()==paths_limit); + }; + if (isTraceEnabled()) logger().trace("Finished loading changed paths "+paths.size()+" paths, "+(commit_is_trimmed ? " commit list is TRIMMED to web.maxCommitPaths":"")); // add commit diffstat int insertions = 0; int deletions = 0; @@ -159,9 +182,9 @@ public void populateItem(final Item item) { insertions += pcm.insertions; deletions += pcm.deletions; } - add(new DiffStatPanel("diffStat", insertions, deletions)); + add(new DiffStatPanel("diffStat", insertions, deletions, false, commit_is_trimmed)); - add(new CommitLegendPanel("commitLegend", paths)); + add(new CommitLegendPanel("commitLegend", paths, commit_is_trimmed)); ListDataProvider pathsDp = new ListDataProvider(paths); DataView pathsView = new DataView("changedPath", pathsDp) { private static final long serialVersionUID = 1L; @@ -169,6 +192,7 @@ public void populateItem(final Item item) { @Override public void populateItem(final Item item) { + if (isTraceEnabled()) logger().trace("Polulating commit path item "+item.getModelObject()); final PathChangeModel entry = item.getModelObject(); Label changeType = new Label("changeType", ""); @@ -330,6 +354,8 @@ public void write(OutputStream output) { } }; add(pathsView); + + if (isTraceEnabled()) logger().trace("Building commits page for:"+r+" commit "+c+" finished."); } @Override diff --git a/src/main/java/com/gitblit/wicket/pages/EditFilePage.java b/src/main/java/com/gitblit/wicket/pages/EditFilePage.java index dbf8a79e2..5ec9b6ee8 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditFilePage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditFilePage.java @@ -123,7 +123,7 @@ protected void onSubmit() { try { ObjectId docAtLoad = getRepository().resolve(commitIdAtLoad.getObject()); - logger.trace("Commiting Edit File page: " + commitIdAtLoad.getObject()); + logger().trace("Commiting Edit File page: " + commitIdAtLoad.getObject()); DirCache index = DirCache.newInCore(); DirCacheBuilder builder = index.builder(); diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index bf3eea8ba..510ed2765 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -570,7 +570,23 @@ protected void onSubmit() { getString("gb.skipSummaryMetricsDescription"), new PropertyModel(repositoryModel, "skipSummaryMetrics"))); + //We need to prepare list of pre-defined values and include the currently stored value. List maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500); + { + Integer current = repositoryModel.maxActivityCommits; + if (!maxActivityCommits.contains(current)) + { + //insert it in a apropriate location. The easiest by laughably costly way + //is to just add and sort. This is is not a problem, since this type of + //action will be necessary only when server setup was modified in such a way, + //that default value of web.maxActivityCommits is not on the allowed above + //list. Why? Bite me. + maxActivityCommits = new ArrayList(maxActivityCommits); + maxActivityCommits.add(current); + Collections.sort(maxActivityCommits); + }; + }; + form.add(new ChoiceOption("maxActivityCommits", getString("gb.maxActivityCommits"), getString("gb.maxActivityCommitsDescription"), diff --git a/src/main/java/com/gitblit/wicket/pages/MetricsPage.java b/src/main/java/com/gitblit/wicket/pages/MetricsPage.java index 96113b0f6..77811687a 100644 --- a/src/main/java/com/gitblit/wicket/pages/MetricsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MetricsPage.java @@ -94,7 +94,7 @@ private void createLineChart(Charts charts, String id, List metrics) { try { date = df.parse(metric.name); } catch (ParseException e) { - logger.error("Unable to parse date: " + metric.name); + logger().error("Unable to parse date: " + metric.name); return; } chart.addValue(date, (int)metric.count); diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java index 36c5ae16c..1f9d64e74 100644 --- a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java @@ -78,7 +78,7 @@ public abstract class RepositoryPage extends RootPage { - protected final Logger logger = LoggerFactory.getLogger(getClass()); + //protected final Logger logger = LoggerFactory.getLogger(getClass()); private final String PARAM_STAR = "star"; @@ -144,7 +144,7 @@ public RepositoryPage(PageParameters params) { try { app().gitblit().reviseUser(user.username, user); } catch (GitBlitException e) { - logger.error("Failed to update user " + user.username, e); + logger().error("Failed to update user " + user.username, e); error(getString("gb.failedToUpdateUser"), false); } } @@ -233,13 +233,13 @@ private List registerNavLinks() { navLinks.add(new PageNavLink("gb.tree", TreePage.class, objectParams)); if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(model) || app().tickets().hasTickets(model))) { PageParameters tParams = WicketUtils.newOpenTicketsParameter(getRepositoryName()); - navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams)); - } + navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams)); + } navLinks.add(new PageNavLink("gb.docs", DocsPage.class, objectParams, true)); if (app().settings().getBoolean(Keys.web.allowForking, true)) { navLinks.add(new PageNavLink("gb.forks", ForksPage.class, params, true)); } - navLinks.add(new PageNavLink("gb.compare", ComparePage.class, params, true)); + navLinks.add(new PageNavLink("gb.compare", ComparePage.class, params, true)); // conditional links // per-repository extra navlinks diff --git a/src/main/java/com/gitblit/wicket/pages/SessionPage.java b/src/main/java/com/gitblit/wicket/pages/SessionPage.java index d715aaeef..5f387fe86 100644 --- a/src/main/java/com/gitblit/wicket/pages/SessionPage.java +++ b/src/main/java/com/gitblit/wicket/pages/SessionPage.java @@ -31,6 +31,27 @@ import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; +/** + A base of "wicket" web pages. + +

Thread safety

+ As it seems that wickets ensure that page exists + only during a duration of a session and is handled + in only one thread no thread safety measures are + necessay since page instance code is never run concurrently. +

+ + Is saying: +

    +
  • Never share component object instances, models, + and behaviors between pages that are in several page maps. + Although the chance that a user will trigger two pages in different + page maps at the same time is slight, it’s possible, + especially with pages that take a while to render.
  • +
  • Application objects, session objects, and session stores aren’t + thread-safe.
  • +
+*/ public abstract class SessionPage extends WebPage { public SessionPage() { diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java index 3cfa152e8..1a5f05182 100644 --- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java @@ -190,7 +190,7 @@ private Charts createCharts(List metrics) { try { date = df.parse(metric.name); } catch (ParseException e) { - logger.error("Unable to parse date: " + metric.name); + logger().error("Unable to parse date: " + metric.name); return charts; } chart.addValue(date, (int)metric.count); diff --git a/src/main/java/com/gitblit/wicket/pages/TicketPage.java b/src/main/java/com/gitblit/wicket/pages/TicketPage.java index e2133966a..d212e3be6 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketPage.java @@ -1451,7 +1451,7 @@ public void run() { } else { // merge failure String msg = MessageFormat.format("Failed to merge ticket {0,number,0}: {1}", ticket.number, result.name()); - logger.error(msg); + logger().error(msg); GitBlitWebSession.get().cacheErrorMessage(msg); } } @@ -1461,13 +1461,13 @@ public void run() { String msg = MessageFormat.format("Can not merge ticket {0,number,0}, patchset {1,number,0} has been vetoed!", ticket.number, patchset.number); GitBlitWebSession.get().cacheErrorMessage(msg); - logger.error(msg); + logger().error(msg); } } else { // not current patchset String msg = MessageFormat.format("Can not merge ticket {0,number,0}, the patchset has been updated!", ticket.number); GitBlitWebSession.get().cacheErrorMessage(msg); - logger.error(msg); + logger().error(msg); } redirectTo(TicketsPage.class, getPageParameters()); diff --git a/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.html b/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.html index 71063626c..54bd9f791 100644 --- a/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.html @@ -5,9 +5,10 @@ lang="en"> +
[more changes]
[change type] [description] -
+
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.java b/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.java index 3f31effe4..bba52df4f 100644 --- a/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/CommitLegendPanel.java @@ -29,15 +29,30 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider; import org.eclipse.jgit.diff.DiffEntry.ChangeType; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.wicket.WicketUtils; public class CommitLegendPanel extends Panel { private static final long serialVersionUID = 1L; - - public CommitLegendPanel(String id, List paths) { + static final Logger LOGGER = LoggerFactory.getLogger(CommitLegendPanel.class); + static final boolean TRACE = LOGGER.isTraceEnabled(); + static final boolean DEBUG = LOGGER.isDebugEnabled(); + + public CommitLegendPanel(String id, List paths) { this(id, paths, false) ;}; + /** Creates + @param id wicket idendtifier + @param paths list of changed paths + @param approx true if paths do not represent a full set of changes + present in commit due to, for an example, some limits. + */ + public CommitLegendPanel(String id, List paths, final boolean approx) { super(id); + if (TRACE) LOGGER.trace("new CommitLegendPanel("+id+",paths.size()="+paths.size()+", approx="+approx+")"); final Map stats = getChangedPathsStats(paths); ListDataProvider legendDp = new ListDataProvider( new ArrayList(stats.keySet())); @@ -73,9 +88,13 @@ public void populateItem(final Item item) { item.add(new Label("description", description)); } }; - add(legendsView); + //Note: There is a known problem which I can't handle, that is "moreChanges" do appear + //on web BEFORE "legend" if in html is AFTER "description". + add(new Label("moreChanges",getString("gb.CommitLegendPanel.moreChanges")).setVisible(approx)); + add(legendsView); + } - + protected Map getChangedPathsStats(List paths) { Map stats = new HashMap(); for (PathChangeModel path : paths) { diff --git a/src/main/java/com/gitblit/wicket/panels/DiffStatPanel.java b/src/main/java/com/gitblit/wicket/panels/DiffStatPanel.java index 30a89027e..c836178bd 100644 --- a/src/main/java/com/gitblit/wicket/panels/DiffStatPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/DiffStatPanel.java @@ -20,6 +20,9 @@ import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.panel.Panel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.gitblit.utils.DiffUtils; import com.gitblit.utils.DiffUtils.NormalizedDiffStat; import com.gitblit.wicket.WicketUtils; @@ -33,6 +36,10 @@ public class DiffStatPanel extends Panel { private static final long serialVersionUID = 1L; + static final Logger LOGGER = LoggerFactory.getLogger(DiffStatPanel.class); + static final boolean TRACE = LOGGER.isTraceEnabled(); + static final boolean DEBUG = LOGGER.isDebugEnabled(); + final int total; @@ -41,13 +48,28 @@ public class DiffStatPanel extends Panel { final int deletions; final boolean inline; - + + final boolean approx; + public DiffStatPanel(String wicketId, int insertions, int deletions) { this(wicketId, insertions, deletions, false); } - public DiffStatPanel(String wicketId, int insertions, int deletions, boolean inline) { + this(wicketId, insertions, deletions, inline,false); + }; + /** Creates + @param wicketId wicket identifier + @param insertions total number of insertions within a commit. + @param deletions total number of deletions within a commit. + @param inline true if panel is inline with commit file and represents stats of single file + or flase if used in header and represents stats of commit. + @param approx true if number of insertions and deletions is approximate, ie because + commit processing was limited in server settings. + */ + public DiffStatPanel(String wicketId, int insertions, int deletions, boolean inline, boolean approx) { super(wicketId); + if (TRACE) LOGGER.trace("new DiffStatPanel("+wicketId+",insertions="+insertions+",deletions="+deletions+",inline="+inline+",approx="+approx); + this.approx = approx; this.insertions = insertions; this.deletions = deletions; this.total = insertions + deletions; @@ -56,9 +78,11 @@ public DiffStatPanel(String wicketId, int insertions, int deletions, boolean inl @Override protected void onInitialize() { + if (TRACE) LOGGER.trace("DiffStatPanel.onInitialize() ENTER"); + super.onInitialize(); - - final String diffStat = MessageFormat.format(getString("gb.diffStat"), "" + insertions, "" + deletions); + + final String diffStat = MessageFormat.format(getString("gb.diffStat"), "" + insertions, "" + deletions, approx ? 1 :0 ); WicketUtils.setHtmlTooltip(this, diffStat); final NormalizedDiffStat n = DiffUtils.normalizeDiffStat(5, insertions, deletions); @@ -69,8 +93,8 @@ protected void onInitialize() { } else { segment = "■"; } - - add(new Label("total", String.valueOf(total))); + + add(new Label("total",MessageFormat.format(getString("gb.diffStat.total"),String.valueOf(total), approx ? 1 :0))); add(new Label("insertions", timesRepeat(n.insertions, segment)).setEscapeModelStrings(false).setVisible(n.insertions > 0)); add(new Label("deletions", timesRepeat(n.deletions, segment)).setEscapeModelStrings(false).setVisible(n.deletions > 0)); add(new Label("blank", timesRepeat(n.blanks, segment)).setEscapeModelStrings(false).setVisible(n.blanks > 0)); @@ -82,6 +106,8 @@ protected void onInitialize() { } setVisible(total > 0); + + if (TRACE) LOGGER.trace("DiffStatPanel.onInitialize() LEAVE"); } String timesRepeat(int cnt, String s) { diff --git a/src/main/java/log4j.properties b/src/main/java/log4j.properties index 43d31d80b..74b1854a9 100644 --- a/src/main/java/log4j.properties +++ b/src/main/java/log4j.properties @@ -5,26 +5,42 @@ # appenders. For the console, use 'S'. For the daily rolling file, use 'R'. # For an HTML formatted log, use 'H'. # -# To override the default (rootCategory) log level, define a property of the +# To override the default (rootLogger) log level, define a property of the # form (see below for available values): # -# log4j.logger. = +# log4j.logger.xxx = # -# Available logger names: -# TODO # -# Possible Log Levels: -# FATAL, ERROR, WARN, INFO, DEBUG +# Possible Log Levels, from more serious to less serious +# OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL +# # #------------------------------------------------------------------------------ -log4j.rootCategory=INFO, S -#log4j.rootLogger=INFO -#log4j.logger.org=INFO -#log4j.logger.com=INFO -#log4j.logger.net=INFO +# Set up main level filtering: +# log4j.rootLogger=, +# where: +# - any log event which is at least that serious will be logged, ie. +# +# This value will be overriden to "DEBUG" if server is configured with web.debugMode==true +# in "data/default.properties" file. +# +# - one of defined below log4j.appender. "appenders" +# which do decide where the logs will be stored/printed to. +# +# This value will be overriden to R if server is run with --dailyLogFile +# +# Default: log4j.rootLogger=INFO, S +# Log importance "Info" to "console". +# + +# Note: change in this option should be consulted with GitBlitServer.java +# Note: this optin may be overrided with web.debugMode +log4j.rootLogger=INFO, S -#log4j.logger.com.gitblit=DEBUG +# Note: change in this option should be consulted with GitBlitServer.java +# Note: this optin may be overrided with web.debugMode +log4j.logger.com.gitblit=INFO log4j.logger.com.gitblit.transport.ssh.SshServerSession=WARN log4j.logger.org.apache.sshd=WARN log4j.logger.org.apache.mina=WARN @@ -39,6 +55,7 @@ log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=WARN # See http://logging.apache.org/log4j/docs/api/index.html for details. # #------------------------------------------------------------------------------ +# Note: change in this option should be consulted with GitBlitServer.java log4j.appender.S = org.apache.log4j.ConsoleAppender log4j.appender.S.layout = org.apache.log4j.PatternLayout log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [%-5p] %m%n @@ -49,7 +66,12 @@ log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [%-5p] %m%n # See http://logging.apache.org/log4j/docs/api/index.html for details. # #------------------------------------------------------------------------------ +# Note: change in this option should be consulted with GitBlitServer.java log4j.appender.R = org.apache.log4j.DailyRollingFileAppender +# If below value is: +# logs/gitblit.log +# it will be overrided to $baseFolder/logs/gitblit.log +# if server is started with --dailyLogFile option. log4j.appender.R.File = logs/gitblit.log log4j.appender.R.Append = true log4j.appender.R.DatePattern = '.'yyyy-MM-dd diff --git a/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java b/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java index 8d6d703b2..215ca516b 100644 --- a/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java +++ b/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java @@ -15,43 +15,7 @@ public class GitBlitServer4UITests extends GitBlitServer { public static void main(String... args) { - GitBlitServer4UITests server = new GitBlitServer4UITests(); - - // filter out the baseFolder parameter - List filtered = new ArrayList(); - String folder = "data"; - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - if (arg.equals("--baseFolder")) { - if (i + 1 == args.length) { - System.out.println("Invalid --baseFolder parameter!"); - System.exit(-1); - } else if (args[i + 1] != ".") { - folder = args[i + 1]; - } - i = i + 1; - } else { - filtered.add(arg); - } - } - - Params.baseFolder = folder; - Params params = new Params(); - CmdLineParser parser = new CmdLineParser(params); - try { - parser.parseArgument(filtered); - if (params.help) { - server.usage(parser, null); - } - } catch (CmdLineException t) { - server.usage(parser, t); - } - - if (params.stop) { - server.stop(params); - } else { - server.start(params); - } + GitBlitServer.main(GitBlitServer4UITests.class, args); } @Override