+ If {@link #logger} is already initialized this method does not do + anything. +
+ This method is using data stored in: +
/log4j.properties
in jar properties file;/log4j.properties
stored in base folder
+ as an override to internal jar properties file;web.debugMode
setting in defaults.properties
+ and gitblit.properties
files;--dailyLogFile
command line option.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]
-
+