| | |
| | | */
|
| | | package com.gitblit;
|
| | |
|
| | | import java.io.BufferedReader;
|
| | | import java.io.File;
|
| | | import java.io.FileFilter;
|
| | | import java.io.IOException;
|
| | | import java.io.InputStream;
|
| | | import java.io.InputStreamReader;
|
| | | import java.lang.reflect.Field;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Arrays;
|
| | | import java.util.Collection;
|
| | | import java.util.Collections;
|
| | | import java.util.HashMap;
|
| | | import java.util.List;
|
| | |
| | |
|
| | | import javax.mail.Message;
|
| | | import javax.mail.MessagingException;
|
| | | import javax.servlet.ServletContext;
|
| | | import javax.servlet.ServletContextEvent;
|
| | | import javax.servlet.ServletContextListener;
|
| | | import javax.servlet.http.Cookie;
|
| | |
| | | import com.gitblit.Constants.FederationToken;
|
| | | import com.gitblit.models.FederationModel;
|
| | | import com.gitblit.models.FederationProposal;
|
| | | import com.gitblit.models.FederationSet;
|
| | | import com.gitblit.models.Metric;
|
| | | import com.gitblit.models.ObjectCache;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.ServerSettings;
|
| | | import com.gitblit.models.ServerStatus;
|
| | | import com.gitblit.models.SettingModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.ByteFormat;
|
| | | import com.gitblit.utils.FederationUtils;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.JsonUtils;
|
| | | import com.gitblit.utils.MetricUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | | /**
|
| | |
| | |
|
| | | private final Map<String, FederationModel> federationPullResults = new ConcurrentHashMap<String, FederationModel>();
|
| | |
|
| | | private final ObjectCache<Long> repositorySizeCache = new ObjectCache<Long>();
|
| | |
|
| | | private final ObjectCache<List<Metric>> repositoryMetricsCache = new ObjectCache<List<Metric>>();
|
| | |
|
| | | private RepositoryResolver<Void> repositoryResolver;
|
| | |
|
| | | private ServletContext servletContext;
|
| | |
|
| | | private File repositoriesFolder;
|
| | |
|
| | |
| | | private IUserService userService;
|
| | |
|
| | | private IStoredSettings settings;
|
| | |
|
| | | private ServerSettings settingsModel;
|
| | |
|
| | | private ServerStatus serverStatus;
|
| | |
|
| | | private MailExecutor mailExecutor;
|
| | |
|
| | |
| | | */
|
| | | public static boolean isDebugMode() {
|
| | | return self().settings.getBoolean(Keys.web.debugMode, false);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Updates the list of server settings.
|
| | | * |
| | | * @param settings
|
| | | * @return true if the update succeeded
|
| | | */
|
| | | public boolean updateSettings(Collection<SettingModel> settings) {
|
| | | // TODO update the settings
|
| | | return false;
|
| | | }
|
| | |
|
| | | public ServerStatus getStatus() {
|
| | | // update heap memory status
|
| | | serverStatus.heapAllocated = Runtime.getRuntime().totalMemory();
|
| | | serverStatus.heapFree = Runtime.getRuntime().freeMemory();
|
| | | return serverStatus;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | */
|
| | | public void updateUserModel(String username, UserModel user, boolean isCreate)
|
| | | throws GitBlitException {
|
| | | if (!username.equalsIgnoreCase(user.username)) {
|
| | | if (userService.getUserModel(user.username) != null) {
|
| | | throw new GitBlitException(MessageFormat.format(
|
| | | "Failed to rename ''{0}'' because ''{1}'' already exists.", username,
|
| | | user.username));
|
| | | }
|
| | | }
|
| | | if (!userService.updateUserModel(username, user)) {
|
| | | throw new GitBlitException(isCreate ? "Failed to add user!" : "Failed to update user!");
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Clears all the cached data for the specified repository.
|
| | | * |
| | | * @param repositoryName
|
| | | */
|
| | | public void clearRepositoryCache(String repositoryName) {
|
| | | repositorySizeCache.remove(repositoryName);
|
| | | repositoryMetricsCache.remove(repositoryName);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | repositories.add(model);
|
| | | }
|
| | | }
|
| | | if (getBoolean(Keys.web.showRepositorySizes, true)) {
|
| | | int repoCount = 0;
|
| | | long startTime = System.currentTimeMillis();
|
| | | ByteFormat byteFormat = new ByteFormat();
|
| | | for (RepositoryModel model : repositories) {
|
| | | if (!model.skipSizeCalculation) {
|
| | | repoCount++;
|
| | | model.size = byteFormat.format(calculateSize(model));
|
| | | }
|
| | | }
|
| | | long duration = System.currentTimeMillis() - startTime;
|
| | | logger.info(MessageFormat.format("{0} repository sizes calculated in {1} msecs",
|
| | | repoCount, duration));
|
| | | }
|
| | | return repositories;
|
| | | }
|
| | |
|
| | |
| | | model.showRemoteBranches = getConfig(config, "showRemoteBranches", false);
|
| | | model.isFrozen = getConfig(config, "isFrozen", false);
|
| | | model.showReadme = getConfig(config, "showReadme", false);
|
| | | model.skipSizeCalculation = getConfig(config, "skipSizeCalculation", false);
|
| | | model.skipSummaryMetrics = getConfig(config, "skipSummaryMetrics", false);
|
| | | model.federationStrategy = FederationStrategy.fromName(getConfig(config,
|
| | | "federationStrategy", null));
|
| | | model.federationSets = new ArrayList<String>(Arrays.asList(config.getStringList(
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the size in bytes of the repository.
|
| | | * Returns the size in bytes of the repository. Gitblit caches the
|
| | | * repository sizes to reduce the performance penalty of recursive
|
| | | * calculation. The cache is updated if the repository has been changed
|
| | | * since the last calculation.
|
| | | *
|
| | | * @param model
|
| | | * @return size in bytes
|
| | | */
|
| | | public long calculateSize(RepositoryModel model) {
|
| | | if (repositorySizeCache.hasCurrent(model.name, model.lastChange)) {
|
| | | return repositorySizeCache.getObject(model.name);
|
| | | }
|
| | | File gitDir = FileKey.resolve(new File(repositoriesFolder, model.name), FS.DETECTED);
|
| | | return com.gitblit.utils.FileUtils.folderSize(gitDir);
|
| | | long size = com.gitblit.utils.FileUtils.folderSize(gitDir);
|
| | | repositorySizeCache.updateObject(model.name, model.lastChange, size);
|
| | | return size;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the gitblit string vlaue for the specified key. If key is not
|
| | | * Returns the metrics for the default branch of the specified repository.
|
| | | * This method builds a metrics cache. The cache is updated if the
|
| | | * repository is updated. A new copy of the metrics list is returned on each
|
| | | * call so that modifications to the list are non-destructive.
|
| | | * |
| | | * @param model
|
| | | * @param repository
|
| | | * @return a new array list of metrics
|
| | | */
|
| | | public List<Metric> getRepositoryDefaultMetrics(RepositoryModel model, Repository repository) {
|
| | | if (repositoryMetricsCache.hasCurrent(model.name, model.lastChange)) {
|
| | | return new ArrayList<Metric>(repositoryMetricsCache.getObject(model.name));
|
| | | }
|
| | | List<Metric> metrics = MetricUtils.getDateMetrics(repository, null, true, null);
|
| | | repositoryMetricsCache.updateObject(model.name, model.lastChange, metrics);
|
| | | return new ArrayList<Metric>(metrics);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the gitblit string value for the specified key. If key is not
|
| | | * set, returns defaultValue.
|
| | | *
|
| | | * @param config
|
| | |
| | | } else {
|
| | | // rename repository
|
| | | if (!repositoryName.equalsIgnoreCase(repository.name)) {
|
| | | if (!repository.name.toLowerCase().endsWith(
|
| | | org.eclipse.jgit.lib.Constants.DOT_GIT_EXT)) {
|
| | | repository.name += org.eclipse.jgit.lib.Constants.DOT_GIT_EXT;
|
| | | }
|
| | | if (new File(repositoriesFolder, repository.name).exists()) {
|
| | | throw new GitBlitException(MessageFormat.format(
|
| | | "Failed to rename ''{0}'' because ''{1}'' already exists.",
|
| | | repositoryName, repository.name));
|
| | | }
|
| | | closeRepository(repositoryName);
|
| | | File folder = new File(repositoriesFolder, repositoryName);
|
| | | File destFolder = new File(repositoriesFolder, repository.name);
|
| | |
| | | "Failed to rename repository permissions ''{0}'' to ''{1}''.",
|
| | | repositoryName, repository.name));
|
| | | }
|
| | |
|
| | | // clear the cache
|
| | | clearRepositoryCache(repositoryName);
|
| | | }
|
| | |
|
| | | // load repository
|
| | |
| | | config.setBoolean("gitblit", null, "showRemoteBranches", repository.showRemoteBranches);
|
| | | config.setBoolean("gitblit", null, "isFrozen", repository.isFrozen);
|
| | | config.setBoolean("gitblit", null, "showReadme", repository.showReadme);
|
| | | config.setBoolean("gitblit", null, "skipSizeCalculation", repository.skipSizeCalculation);
|
| | | config.setBoolean("gitblit", null, "skipSummaryMetrics", repository.skipSummaryMetrics);
|
| | | config.setStringList("gitblit", null, "federationSets", repository.federationSets);
|
| | | config.setString("gitblit", null, "federationStrategy",
|
| | | repository.federationStrategy.name());
|
| | |
| | | return true;
|
| | | }
|
| | | }
|
| | |
|
| | | // clear the repository cache
|
| | | clearRepositoryCache(repositoryName);
|
| | | } catch (Throwable t) {
|
| | | logger.error(MessageFormat.format("Failed to delete repository {0}", repositoryName), t);
|
| | | }
|
| | |
| | | }
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of federation sets.
|
| | | * |
| | | * @return list of federation sets
|
| | | */
|
| | | public List<FederationSet> getFederationSets(String gitblitUrl) {
|
| | | List<FederationSet> list = new ArrayList<FederationSet>();
|
| | | // generate standard tokens
|
| | | for (FederationToken type : FederationToken.values()) {
|
| | | FederationSet fset = new FederationSet(type.toString(), type, getFederationToken(type));
|
| | | fset.repositories = getRepositories(gitblitUrl, fset.token);
|
| | | list.add(fset);
|
| | | }
|
| | | // generate tokens for federation sets
|
| | | for (String set : settings.getStrings(Keys.federation.sets)) {
|
| | | FederationSet fset = new FederationSet(set, FederationToken.REPOSITORIES,
|
| | | getFederationToken(set));
|
| | | fset.repositories = getRepositories(gitblitUrl, fset.token);
|
| | | list.add(fset);
|
| | | }
|
| | | return list;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | });
|
| | | for (File file : files) {
|
| | | String json = com.gitblit.utils.FileUtils.readContent(file, null);
|
| | | FederationProposal proposal = JsonUtils.fromJsonString(json, FederationProposal.class);
|
| | | FederationProposal proposal = JsonUtils.fromJsonString(json,
|
| | | FederationProposal.class);
|
| | | list.add(proposal);
|
| | | }
|
| | | }
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the descriptions/comments of the Gitblit config settings.
|
| | | * |
| | | * @return SettingsModel
|
| | | */
|
| | | public ServerSettings getSettingsModel() {
|
| | | // ensure that the current values are updated in the setting models
|
| | | settingsModel.updateCurrentValues(settings);
|
| | | return settingsModel;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Parse the properties file and aggregate all the comments by the setting
|
| | | * key. A setting model tracks the current value, the default value, the
|
| | | * description of the setting and and directives about the setting.
|
| | | * |
| | | * @return Map<String, SettingModel>
|
| | | */
|
| | | private ServerSettings loadSettingModels() {
|
| | | ServerSettings settingsModel = new ServerSettings();
|
| | | try {
|
| | | // Read bundled Gitblit properties to extract setting descriptions.
|
| | | // This copy is pristine and only used for populating the setting
|
| | | // models map.
|
| | | InputStream is = servletContext.getResourceAsStream("/WEB-INF/gitblit.properties");
|
| | | BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is));
|
| | | StringBuilder description = new StringBuilder();
|
| | | SettingModel setting = new SettingModel();
|
| | | String line = null;
|
| | | while ((line = propertiesReader.readLine()) != null) {
|
| | | if (line.length() == 0) {
|
| | | description.setLength(0);
|
| | | setting = new SettingModel();
|
| | | } else {
|
| | | if (line.charAt(0) == '#') {
|
| | | if (line.length() > 1) {
|
| | | String text = line.substring(1).trim();
|
| | | if (SettingModel.CASE_SENSITIVE.equals(text)) {
|
| | | setting.caseSensitive = true;
|
| | | } else if (SettingModel.RESTART_REQUIRED.equals(text)) {
|
| | | setting.restartRequired = true;
|
| | | } else if (SettingModel.SPACE_DELIMITED.equals(text)) {
|
| | | setting.spaceDelimited = true;
|
| | | } else if (text.startsWith(SettingModel.SINCE)) {
|
| | | try {
|
| | | setting.since = text.split(" ")[1];
|
| | | } catch (Exception e) {
|
| | | setting.since = text;
|
| | | }
|
| | | } else {
|
| | | description.append(text);
|
| | | description.append('\n');
|
| | | }
|
| | | }
|
| | | } else {
|
| | | String[] kvp = line.split("=", 2);
|
| | | String key = kvp[0].trim();
|
| | | setting.name = key;
|
| | | setting.defaultValue = kvp[1].trim();
|
| | | setting.currentValue = setting.defaultValue;
|
| | | setting.description = description.toString().trim();
|
| | | settingsModel.add(setting);
|
| | | description.setLength(0);
|
| | | setting = new SettingModel();
|
| | | }
|
| | | }
|
| | | }
|
| | | propertiesReader.close();
|
| | | } catch (NullPointerException e) {
|
| | | logger.error("Failed to find resource copy of gitblit.properties");
|
| | | } catch (IOException e) {
|
| | | logger.error("Failed to load resource copy of gitblit.properties");
|
| | | }
|
| | | return settingsModel;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Configure the Gitblit singleton with the specified settings source. This
|
| | | * source may be file settings (Gitblit GO) or may be web.xml settings
|
| | | * (Gitblit WAR).
|
| | |
| | | repositoriesFolder = new File(settings.getString(Keys.git.repositoriesFolder, "git"));
|
| | | logger.info("Git repositories folder " + repositoriesFolder.getAbsolutePath());
|
| | | repositoryResolver = new FileResolver<Void>(repositoriesFolder, exportAll);
|
| | | serverStatus = new ServerStatus();
|
| | | String realm = settings.getString(Keys.realm.userService, "users.properties");
|
| | | IUserService loginService = null;
|
| | | try {
|
| | |
| | | */
|
| | | @Override
|
| | | public void contextInitialized(ServletContextEvent contextEvent) {
|
| | | servletContext = contextEvent.getServletContext();
|
| | | settingsModel = loadSettingModels();
|
| | | if (settings == null) {
|
| | | // Gitblit WAR is running in a servlet container
|
| | | WebXmlSettings webxmlSettings = new WebXmlSettings(contextEvent.getServletContext());
|