Fix issue #1344 - Reviewer appears duplicated

This commit is contained in:
Robin Shen 2023-04-20 10:37:45 +08:00
parent 7c90f0388c
commit 1ff550d53f
57 changed files with 935 additions and 843 deletions

View File

@ -9,7 +9,7 @@
<version>1.2.0</version>
</parent>
<artifactId>server</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
<packaging>pom</packaging>
<build>
<finalName>${project.groupId}.${project.artifactId}-${project.version}</finalName>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<build>
<plugins>

View File

@ -212,7 +212,7 @@ public class CoreModule extends AbstractPluginModule {
bind(SshManager.class).to(DefaultSshManager.class);
bind(MarkdownManager.class).to(DefaultMarkdownManager.class);
bind(SettingManager.class).to(DefaultSettingManager.class);
bind(DataManager.class).to(DefaultDataManager.class);
bind(PersistenceManager.class).to(DefaultPersistenceManager.class);
bind(TaskScheduler.class).to(DefaultTaskScheduler.class);
bind(PullRequestCommentManager.class).to(DefaultPullRequestCommentManager.class);
bind(CodeCommentManager.class).to(DefaultCodeCommentManager.class);
@ -540,7 +540,7 @@ public class CoreModule extends AbstractPluginModule {
}
private void configurePersistence() {
bind(DataManager.class).to(DefaultDataManager.class);
bind(PersistenceManager.class).to(DefaultPersistenceManager.class);
bind(Session.class).toProvider(SessionProvider.class);
bind(EntityManager.class).toProvider(SessionProvider.class);

View File

@ -18,13 +18,15 @@ import io.onedev.server.event.system.SystemStopped;
import io.onedev.server.event.system.SystemStopping;
import io.onedev.server.exception.ServerNotReadyException;
import io.onedev.server.jetty.JettyLauncher;
import io.onedev.server.persistence.*;
import io.onedev.server.persistence.IdManager;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.persistence.annotation.Sessional;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.util.UrlUtils;
import io.onedev.server.util.init.InitStage;
import io.onedev.server.util.schedule.TaskScheduler;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.request.Url;
import org.eclipse.jgit.util.FS.FileStoreAttributes;
@ -41,24 +43,27 @@ import javax.ws.rs.core.Response;
import java.io.*;
import java.net.ServerSocket;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.Date;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import static io.onedev.commons.utils.FileUtils.loadProperties;
import static io.onedev.k8shelper.KubernetesHelper.BEARER;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION;
public class OneDev extends AbstractPlugin implements Serializable {
private static final Logger logger = LoggerFactory.getLogger(OneDev.class);
private final Provider<JettyLauncher> jettyLauncherProvider;
private final SessionManager sessionManager;
private final DataManager dataManager;
private final PersistenceManager persistenceManager;
private final Provider<ServerConfig> serverConfigProvider;
@ -80,15 +85,15 @@ public class OneDev extends AbstractPlugin implements Serializable {
// Some are injected via provider as instantiation might encounter problem during upgrade
@Inject
public OneDev(Provider<JettyLauncher> jettyLauncherProvider, TaskScheduler taskScheduler,
SessionManager sessionManager, Provider<ServerConfig> serverConfigProvider,
DataManager dataManager, ExecutorService executorService,
ListenerRegistry listenerRegistry, ClusterManager clusterManager,
public OneDev(Provider<JettyLauncher> jettyLauncherProvider, TaskScheduler taskScheduler,
SessionManager sessionManager, Provider<ServerConfig> serverConfigProvider,
PersistenceManager persistenceManager, ExecutorService executorService,
ListenerRegistry listenerRegistry, ClusterManager clusterManager,
IdManager idManager, SessionFactoryManager sessionFactoryManager) {
this.jettyLauncherProvider = jettyLauncherProvider;
this.taskScheduler = taskScheduler;
this.sessionManager = sessionManager;
this.dataManager = dataManager;
this.persistenceManager = persistenceManager;
this.serverConfigProvider = serverConfigProvider;
this.executorService = executorService;
this.listenerRegistry = listenerRegistry;
@ -107,22 +112,15 @@ public class OneDev extends AbstractPlugin implements Serializable {
System.setProperty("hsqldb.method_class_names", "java.lang.Math");
sessionFactoryManager.start();
dataManager.callWithConnection((ConnectionCallable<Void>) conn -> {
while (true) {
try {
dataManager.populateDatabase(conn);
break;
} catch (Exception e) {
logger.warn("Error initializing data, will retry later...", e);
try {
Thread.sleep((RandomUtils.nextInt(5)+1)*1000L);
} catch (InterruptedException ignored) {
}
}
}
return null;
});
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
persistenceManager.populateDatabase(conn);
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
};
clusterManager.start();
idManager.init();
@ -137,7 +135,7 @@ public class OneDev extends AbstractPlugin implements Serializable {
HazelcastInstance hazelcastInstance = clusterManager.getHazelcastInstance();
var dataChecked = hazelcastInstance.getCPSubsystem().getAtomicLong("dataInited");
clusterManager.init(dataChecked, () -> {
var manualConfigs = dataManager.checkData();
var manualConfigs = persistenceManager.checkData();
if (!manualConfigs.isEmpty()) {
if (getIngressUrl() != null)
logger.warn("Please set up the server at " + getIngressUrl());
@ -319,7 +317,7 @@ public class OneDev extends AbstractPlugin implements Serializable {
}
public static boolean isServerRunning(File installDir) {
Properties props = FileUtils.loadProperties(new File(installDir, "conf/server.properties"));
Properties props = loadProperties(new File(installDir, "conf/server.properties"));
int sshPort = Integer.parseInt(props.get("ssh_port").toString());
try (ServerSocket ignored = new ServerSocket(sshPort)) {
return false;

View File

@ -17,8 +17,8 @@ import io.onedev.server.event.ListenerRegistry;
import io.onedev.server.event.cluster.ConnectionLost;
import io.onedev.server.event.cluster.ConnectionRestored;
import io.onedev.server.model.ClusterServer;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.replica.ProjectReplica;
import javax.inject.Inject;
@ -34,6 +34,7 @@ import java.util.concurrent.Future;
import static io.onedev.server.model.AbstractEntity.PROP_ID;
import static io.onedev.server.model.ClusterServer.PROP_ADDRESS;
import static io.onedev.server.persistence.PersistenceUtils.callWithDatabaseLock;
import static io.onedev.server.replica.ProjectReplica.Type.PRIMARY;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.max;
@ -46,7 +47,9 @@ public class DefaultClusterManager implements ClusterManager {
private final ServerConfig serverConfig;
private final DataManager dataManager;
private final HibernateConfig hibernateConfig;
private final PersistenceManager persistenceManager;
private final ListenerRegistry listenerRegistry;
@ -61,11 +64,12 @@ public class DefaultClusterManager implements ClusterManager {
private final String credential;
@Inject
public DefaultClusterManager(ServerConfig serverConfig, DataManager dataManager,
public DefaultClusterManager(ServerConfig serverConfig, PersistenceManager persistenceManager,
ListenerRegistry listenerRegistry, HibernateConfig hibernateConfig) {
this.serverConfig = serverConfig;
this.dataManager = dataManager;
this.persistenceManager = persistenceManager;
this.listenerRegistry = listenerRegistry;
this.hibernateConfig = hibernateConfig;
var dbPassword = hibernateConfig.getPassword();
if (dbPassword == null)
dbPassword = "";
@ -81,7 +85,7 @@ public class DefaultClusterManager implements ClusterManager {
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(String.format(
"insert into %s values(%d, '%s')",
dataManager.getTableName(ClusterServer.class), id, server));
persistenceManager.getTableName(ClusterServer.class), id, server));
} catch (SQLException e) {
throw new RuntimeException(e);
}
@ -90,41 +94,43 @@ public class DefaultClusterManager implements ClusterManager {
@Override
public void start() {
var localServer = getLocalServerAddress();
var servers = dataManager.callWithConnection(conn -> {
boolean hasLock;
try (Statement stmt = conn.createStatement()) {
String query = String.format("select * from %s where %s=0 for update",
dataManager.getTableName(ClusterServer.class),
dataManager.getColumnName(PROP_ID));
hasLock = stmt.executeQuery(query).next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (!hasLock)
saveServer(conn, 0L, "lock");
Collection<String> servers;
try (var conn = persistenceManager.openConnection()) {
var callable = new Callable<Collection<String>>() {
var theServers = new HashMap<Long, String>();
try (Statement stmt = conn.createStatement()) {
String query = String.format("select %s, %s from %s where %s!=0",
dataManager.getColumnName(PROP_ID),
dataManager.getColumnName(PROP_ADDRESS),
dataManager.getTableName(ClusterServer.class),
dataManager.getColumnName(PROP_ID));
try (ResultSet resultset = stmt.executeQuery(query)) {
while (resultset.next())
theServers.put(resultset.getLong(1), resultset.getString(2));
@Override
public Collection<String> call() {
var servers = new HashMap<Long, String>();
try (Statement stmt = conn.createStatement()) {
String query = String.format("select %s, %s from %s",
persistenceManager.getColumnName(PROP_ID),
persistenceManager.getColumnName(PROP_ADDRESS),
persistenceManager.getTableName(ClusterServer.class),
persistenceManager.getColumnName(PROP_ID));
try (ResultSet resultset = stmt.executeQuery(query)) {
while (resultset.next())
servers.put(resultset.getLong(1), resultset.getString(2));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (!servers.containsValue(localServer)) {
Long nextId = servers.isEmpty() ? 1L : max(servers.keySet()) + 1L;
saveServer(conn, nextId, localServer);
servers.put(nextId, localServer);
}
return servers.values();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (!theServers.containsValue(localServer)) {
Long nextId = theServers.isEmpty() ? 1L : max(theServers.keySet()) + 1L;
saveServer(conn, nextId, localServer);
theServers.put(nextId, localServer);
}
return theServers;
});
};
if (hibernateConfig.isHSQLDialect())
servers = callable.call();
else
servers = callWithDatabaseLock(conn, callable);
} catch (SQLException e) {
throw new RuntimeException(e);
};
Config config = new Config();
config.setClusterName(credential);
@ -137,7 +143,7 @@ public class DefaultClusterManager implements ClusterManager {
var hasLocalhost = false;
var hasNonLocalhost = false;
for (String server: servers.values()) {
for (String server: servers) {
if (server.startsWith("127.0.0.1:"))
hasLocalhost = true;
else
@ -188,18 +194,19 @@ public class DefaultClusterManager implements ClusterManager {
hazelcastInstance = null;
}
dataManager.callWithConnection(conn -> {
try (var conn = persistenceManager.openConnection()) {
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(String.format(
"delete from %s where %s='%s'",
dataManager.getTableName(ClusterServer.class),
dataManager.getColumnName(PROP_ADDRESS),
persistenceManager.getTableName(ClusterServer.class),
persistenceManager.getColumnName(PROP_ADDRESS),
localServer));
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override

View File

@ -1,24 +1,24 @@
package io.onedev.server.commandhandler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.ConnectionCallable;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.PersistenceUtils;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
@Singleton
public class ApplyDatabaseConstraints extends AbstractPlugin {
@ -29,15 +29,15 @@ public class ApplyDatabaseConstraints extends AbstractPlugin {
private final SessionFactoryManager sessionFactoryManager;
private final DataManager dataManager;
private final PersistenceManager persistenceManager;
private final HibernateConfig hibernateConfig;
@Inject
public ApplyDatabaseConstraints(SessionFactoryManager sessionFactoryManager, DataManager dataManager,
public ApplyDatabaseConstraints(SessionFactoryManager sessionFactoryManager, PersistenceManager persistenceManager,
HibernateConfig hibernateConfig) {
this.sessionFactoryManager = sessionFactoryManager;
this.dataManager = dataManager;
this.persistenceManager = persistenceManager;
this.hibernateConfig = hibernateConfig;
}
@ -52,14 +52,12 @@ public class ApplyDatabaseConstraints extends AbstractPlugin {
sessionFactoryManager.start();
dataManager.callWithConnection(new ConnectionCallable<Void>() {
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
persistenceManager.checkDataVersion(conn, false);
@Override
public Void call(Connection conn) {
dataManager.checkDataVersion(conn, false);
logger.warn("This script is mainly used to apply database constraints after fixing database integrity issues (may happen during restore/upgrade)");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
logger.warn("Press 'y' to run the script, or 'n' to stop");
@ -75,13 +73,13 @@ public class ApplyDatabaseConstraints extends AbstractPlugin {
System.exit(0);
}
dataManager.dropConstraints(conn);
dataManager.applyConstraints(conn);
persistenceManager.dropConstraints(conn);
persistenceManager.applyConstraints(conn);
return null;
}
});
});
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (hibernateConfig.isHSQLDialect()) {
try {

View File

@ -1,101 +1,100 @@
package io.onedev.server.commandhandler;
import java.io.File;
import java.sql.Connection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.commons.utils.ExceptionUtils;
import io.onedev.commons.utils.FileUtils;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.ConnectionCallable;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
@Singleton
public class BackupDatabase extends AbstractPlugin {
public static final String COMMAND = "backup-db";
private static final Logger logger = LoggerFactory.getLogger(BackupDatabase.class);
private final DataManager dataManager;
private final SessionFactoryManager sessionFactoryManager;
private final HibernateConfig hibernateConfig;
@Inject
public BackupDatabase(DataManager dataManager, SessionFactoryManager sessionFactoryManager,
HibernateConfig hibernateConfig) {
this.dataManager = dataManager;
this.sessionFactoryManager = sessionFactoryManager;
this.hibernateConfig = hibernateConfig;
}
@Override
public void start() {
SecurityUtils.bindAsSystem();
if (Bootstrap.command.getArgs().length == 0) {
logger.error("Missing backup file parameter. Usage: {} <path to database backup file>", Bootstrap.command.getScript());
System.exit(1);
}
File backupFile = new File(Bootstrap.command.getArgs()[0]);
if (!backupFile.isAbsolute() && System.getenv("WRAPPER_INIT_DIR") != null)
backupFile = new File(System.getenv("WRAPPER_INIT_DIR"), backupFile.getPath());
if (backupFile.exists()) {
logger.error("Backup file already exists: {}", backupFile.getAbsolutePath());
System.exit(1);
}
if (OneDev.isServerRunning(Bootstrap.installDir) && hibernateConfig.isHSQLDialect()) {
logger.error("Please stop server before backing up database");
System.exit(1);
}
sessionFactoryManager.start();
dataManager.callWithConnection(new ConnectionCallable<Void>() {
@Override
public Void call(Connection conn) {
dataManager.checkDataVersion(conn, false);
return null;
}
});
logger.info("Backing up database to {}...", backupFile.getAbsolutePath());
File tempDir = FileUtils.createTempDir("backup");
try {
dataManager.exportData(tempDir);
FileUtils.zip(tempDir, backupFile, null);
} catch (Exception e) {
throw ExceptionUtils.unchecked(e);
} finally {
FileUtils.deleteDir(tempDir);
}
logger.info("Database is successfully backed up to {}", backupFile.getAbsolutePath());
System.exit(0);
}
@Override
public void stop() {
sessionFactoryManager.stop();
}
}
package io.onedev.server.commandhandler;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.commons.utils.ExceptionUtils;
import io.onedev.commons.utils.FileUtils;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.sql.SQLException;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
@Singleton
public class BackupDatabase extends AbstractPlugin {
public static final String COMMAND = "backup-db";
private static final Logger logger = LoggerFactory.getLogger(BackupDatabase.class);
private final PersistenceManager persistenceManager;
private final SessionFactoryManager sessionFactoryManager;
private final HibernateConfig hibernateConfig;
@Inject
public BackupDatabase(PersistenceManager persistenceManager, SessionFactoryManager sessionFactoryManager,
HibernateConfig hibernateConfig) {
this.persistenceManager = persistenceManager;
this.sessionFactoryManager = sessionFactoryManager;
this.hibernateConfig = hibernateConfig;
}
@Override
public void start() {
SecurityUtils.bindAsSystem();
if (Bootstrap.command.getArgs().length == 0) {
logger.error("Missing backup file parameter. Usage: {} <path to database backup file>", Bootstrap.command.getScript());
System.exit(1);
}
File backupFile = new File(Bootstrap.command.getArgs()[0]);
if (!backupFile.isAbsolute() && System.getenv("WRAPPER_INIT_DIR") != null)
backupFile = new File(System.getenv("WRAPPER_INIT_DIR"), backupFile.getPath());
if (backupFile.exists()) {
logger.error("Backup file already exists: {}", backupFile.getAbsolutePath());
System.exit(1);
}
if (OneDev.isServerRunning(Bootstrap.installDir) && hibernateConfig.isHSQLDialect()) {
logger.error("Please stop server before backing up database");
System.exit(1);
}
sessionFactoryManager.start();
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
persistenceManager.checkDataVersion(conn, false);
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
}
;
logger.info("Backing up database to {}...", backupFile.getAbsolutePath());
File tempDir = FileUtils.createTempDir("backup");
try {
persistenceManager.exportData(tempDir);
FileUtils.zip(tempDir, backupFile, null);
} catch (Exception e) {
throw ExceptionUtils.unchecked(e);
} finally {
FileUtils.deleteDir(tempDir);
}
logger.info("Database is successfully backed up to {}", backupFile.getAbsolutePath());
System.exit(0);
}
@Override
public void stop() {
sessionFactoryManager.stop();
}
}

View File

@ -1,21 +1,20 @@
package io.onedev.server.commandhandler;
import java.sql.Connection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.ConnectionCallable;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.sql.SQLException;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
@Singleton
public class CheckDataVersion extends AbstractPlugin {
@ -26,15 +25,15 @@ public class CheckDataVersion extends AbstractPlugin {
private final SessionFactoryManager sessionFactoryManager;
private final DataManager dataManager;
private final PersistenceManager persistenceManager;
private final HibernateConfig hibernateConfig;
@Inject
public CheckDataVersion(SessionFactoryManager sessionFactoryManager, DataManager dataManager,
public CheckDataVersion(SessionFactoryManager sessionFactoryManager, PersistenceManager persistenceManager,
HibernateConfig hibernateConfig) {
this.sessionFactoryManager = sessionFactoryManager;
this.dataManager = dataManager;
this.persistenceManager = persistenceManager;
this.hibernateConfig = hibernateConfig;
}
@ -51,14 +50,12 @@ public class CheckDataVersion extends AbstractPlugin {
// Use system.out in case logger is suppressed by user as this output is important to
// upgrade procedure
String dataVersion = dataManager.callWithConnection(new ConnectionCallable<String>() {
@Override
public String call(Connection conn) {
return dataManager.checkDataVersion(conn, false);
}
});
String dataVersion;
try (var conn = persistenceManager.openConnection()) {
dataVersion = callWithTransaction(conn, () -> persistenceManager.checkDataVersion(conn, false));
} catch (SQLException e) {
throw new RuntimeException(e);
}
System.out.println("Data version: " + dataVersion);
System.exit(0);
}

View File

@ -1,6 +1,7 @@
package io.onedev.server.commandhandler;
import java.sql.Connection;
import java.sql.SQLException;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -11,8 +12,7 @@ import org.slf4j.LoggerFactory;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.ConnectionCallable;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
@ -26,15 +26,15 @@ public class CleanDatabase extends AbstractPlugin {
private final SessionFactoryManager sessionFactoryManager;
private final DataManager dataManager;
private final PersistenceManager persistenceManager;
private final HibernateConfig hibernateConfig;
@Inject
public CleanDatabase(SessionFactoryManager sessionFactoryManager, DataManager dataManager,
public CleanDatabase(SessionFactoryManager sessionFactoryManager, PersistenceManager persistenceManager,
HibernateConfig hibernateConfig) {
this.sessionFactoryManager = sessionFactoryManager;
this.dataManager = dataManager;
this.persistenceManager = persistenceManager;
this.hibernateConfig = hibernateConfig;
}
@ -53,16 +53,13 @@ public class CleanDatabase extends AbstractPlugin {
// when drop non-existent constraints, and we want to ignore them and
// continue to execute other sql statements without rolling back whole
// transaction
dataManager.callWithConnection(new ConnectionCallable<Void>() {
@Override
public Void call(Connection conn) {
dataManager.checkDataVersion(conn, false);
dataManager.cleanDatabase(conn);
return null;
}
}, true);
try (var conn = persistenceManager.openConnection()) {
conn.setAutoCommit(true);
persistenceManager.checkDataVersion(conn, false);
persistenceManager.cleanDatabase(conn);
} catch (SQLException e) {
throw new RuntimeException(e);
};
if (hibernateConfig.isHSQLDialect()) {
try {

View File

@ -1,24 +1,24 @@
package io.onedev.server.commandhandler;
import java.sql.Connection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.shiro.authc.credential.PasswordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.server.OneDev;
import io.onedev.server.entitymanager.UserManager;
import io.onedev.server.model.User;
import io.onedev.server.persistence.ConnectionCallable;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.PersistenceUtils;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.persistence.TransactionManager;
import io.onedev.server.security.SecurityUtils;
import org.apache.shiro.authc.credential.PasswordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.sql.SQLException;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
@Singleton
public class ResetAdminPassword extends AbstractPlugin {
@ -27,7 +27,7 @@ public class ResetAdminPassword extends AbstractPlugin {
private static final Logger logger = LoggerFactory.getLogger(ResetAdminPassword.class);
private final DataManager dataManager;
private final PersistenceManager persistenceManager;
private final SessionFactoryManager sessionFactoryManager;
@ -36,10 +36,10 @@ public class ResetAdminPassword extends AbstractPlugin {
private final PasswordService passwordService;
@Inject
public ResetAdminPassword(DataManager dataManager, SessionFactoryManager sessionFactoryManager,
UserManager userManager, PasswordService passwordService,
TransactionManager transactionManager) {
this.dataManager = dataManager;
public ResetAdminPassword(PersistenceManager persistenceManager, SessionFactoryManager sessionFactoryManager,
UserManager userManager, PasswordService passwordService,
TransactionManager transactionManager) {
this.persistenceManager = persistenceManager;
this.sessionFactoryManager = sessionFactoryManager;
this.userManager = userManager;
this.passwordService = passwordService;
@ -60,15 +60,14 @@ public class ResetAdminPassword extends AbstractPlugin {
sessionFactoryManager.start();
dataManager.callWithConnection(new ConnectionCallable<Void>() {
@Override
public Void call(Connection conn) {
dataManager.checkDataVersion(conn, false);
return null;
}
});
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
persistenceManager.checkDataVersion(conn, false);
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
};
User root = userManager.get(User.ROOT_ID);
if (root == null) {

View File

@ -1,151 +1,149 @@
package io.onedev.server.commandhandler;
import java.io.File;
import java.sql.Connection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.bootstrap.Command;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.commons.utils.FileUtils;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.ConnectionCallable;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
@Singleton
public class RestoreDatabase extends AbstractPlugin {
private static final Logger logger = LoggerFactory.getLogger(RestoreDatabase.class);
public static final String COMMAND = "restore-db";
private final DataManager dataManager;
private final SessionFactoryManager sessionFactoryManager;
private final HibernateConfig hibernateConfig;
@Inject
public RestoreDatabase(DataManager dataManager, SessionFactoryManager sessionFactoryManager,
HibernateConfig hibernateConfig) {
this.dataManager = dataManager;
this.sessionFactoryManager = sessionFactoryManager;
this.hibernateConfig = hibernateConfig;
}
@Override
public void start() {
SecurityUtils.bindAsSystem();
if (Bootstrap.command.getArgs().length == 0) {
logger.error("Missing backup file parameter. Usage: {} <path to database backup file>", Bootstrap.command.getScript());
System.exit(1);
}
File backupFile = new File(Bootstrap.command.getArgs()[0]);
if (!backupFile.isAbsolute() && System.getenv("WRAPPER_INIT_DIR") != null)
backupFile = new File(System.getenv("WRAPPER_INIT_DIR"), backupFile.getPath());
if (!backupFile.exists()) {
logger.error("Unable to find file: {}", backupFile.getAbsolutePath());
System.exit(1);
}
boolean validateData = true;
if (Bootstrap.command.getArgs().length >= 2)
validateData = Boolean.parseBoolean(Bootstrap.command.getArgs()[1]);
logger.info("Restoring database from {}...", backupFile.getAbsolutePath());
if (OneDev.isServerRunning(Bootstrap.installDir)) {
logger.error("Please stop server before restoring");
System.exit(1);
}
sessionFactoryManager.start();
if (backupFile.isFile()) {
File dataDir = FileUtils.createTempDir("restore");
try {
FileUtils.unzip(backupFile, dataDir);
doRestore(dataDir, validateData);
} finally {
FileUtils.deleteDir(dataDir);
}
} else {
doRestore(backupFile, validateData);
}
if (hibernateConfig.isHSQLDialect()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
logger.info("Database is successfully restored from {}", backupFile.getAbsolutePath());
System.exit(0);
}
private void doRestore(File dataDir, boolean validateData) {
dataManager.migrateData(dataDir);
if (validateData)
dataManager.validateData(dataDir);
dataManager.callWithConnection(new ConnectionCallable<Void>() {
@Override
public Void call(Connection conn) {
String dbDataVersion = dataManager.checkDataVersion(conn, true);
if (dbDataVersion != null) {
logger.info("Cleaning database...");
dataManager.cleanDatabase(conn);
}
logger.info("Creating tables...");
dataManager.createTables(conn);
return null;
}
});
logger.info("Importing data into database...");
dataManager.importData(dataDir);
dataManager.callWithConnection(new ConnectionCallable<Void>() {
@Override
public Void call(Connection conn) {
logger.info("Applying foreign key constraints...");
try {
dataManager.applyConstraints(conn);
} catch (Exception e) {
logger.error("Failed to apply database constraints", e);
logger.info("If above error is caused by foreign key constraint violations, you may fix it via your database sql tool, "
+ "and then run {} to reapply database constraints", Command.getScript("apply-db-constraints"));
System.exit(1);
}
return null;
}
});
}
@Override
public void stop() {
sessionFactoryManager.stop();
}
}
package io.onedev.server.commandhandler;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.bootstrap.Command;
import io.onedev.commons.loader.AbstractPlugin;
import io.onedev.commons.utils.FileUtils;
import io.onedev.server.OneDev;
import io.onedev.server.persistence.HibernateConfig;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.persistence.PersistenceUtils;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.security.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.sql.SQLException;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
@Singleton
public class RestoreDatabase extends AbstractPlugin {
private static final Logger logger = LoggerFactory.getLogger(RestoreDatabase.class);
public static final String COMMAND = "restore-db";
private final PersistenceManager persistenceManager;
private final SessionFactoryManager sessionFactoryManager;
private final HibernateConfig hibernateConfig;
@Inject
public RestoreDatabase(PersistenceManager persistenceManager, SessionFactoryManager sessionFactoryManager,
HibernateConfig hibernateConfig) {
this.persistenceManager = persistenceManager;
this.sessionFactoryManager = sessionFactoryManager;
this.hibernateConfig = hibernateConfig;
}
@Override
public void start() {
SecurityUtils.bindAsSystem();
if (Bootstrap.command.getArgs().length == 0) {
logger.error("Missing backup file parameter. Usage: {} <path to database backup file>", Bootstrap.command.getScript());
System.exit(1);
}
File backupFile = new File(Bootstrap.command.getArgs()[0]);
if (!backupFile.isAbsolute() && System.getenv("WRAPPER_INIT_DIR") != null)
backupFile = new File(System.getenv("WRAPPER_INIT_DIR"), backupFile.getPath());
if (!backupFile.exists()) {
logger.error("Unable to find file: {}", backupFile.getAbsolutePath());
System.exit(1);
}
boolean validateData = true;
if (Bootstrap.command.getArgs().length >= 2)
validateData = Boolean.parseBoolean(Bootstrap.command.getArgs()[1]);
logger.info("Restoring database from {}...", backupFile.getAbsolutePath());
if (OneDev.isServerRunning(Bootstrap.installDir)) {
logger.error("Please stop server before restoring");
System.exit(1);
}
sessionFactoryManager.start();
if (backupFile.isFile()) {
File dataDir = FileUtils.createTempDir("restore");
try {
FileUtils.unzip(backupFile, dataDir);
doRestore(dataDir, validateData);
} finally {
FileUtils.deleteDir(dataDir);
}
} else {
doRestore(backupFile, validateData);
}
if (hibernateConfig.isHSQLDialect()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
logger.info("Database is successfully restored from {}", backupFile.getAbsolutePath());
System.exit(0);
}
private void doRestore(File dataDir, boolean validateData) {
persistenceManager.migrateData(dataDir);
if (validateData)
persistenceManager.validateData(dataDir);
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
String dbDataVersion = persistenceManager.checkDataVersion(conn, true);
if (dbDataVersion != null) {
logger.info("Cleaning database...");
persistenceManager.cleanDatabase(conn);
}
logger.info("Creating tables...");
persistenceManager.createTables(conn);
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
}
logger.info("Importing data into database...");
persistenceManager.importData(dataDir);
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
logger.info("Applying foreign key constraints...");
try {
persistenceManager.applyConstraints(conn);
} catch (Exception e) {
logger.error("Failed to apply database constraints", e);
logger.info("If above error is caused by foreign key constraint violations, you may fix it via your database sql tool, "
+ "and then run {} to reapply database constraints", Command.getScript("apply-db-constraints"));
System.exit(1);
}
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void stop() {
sessionFactoryManager.stop();
}
}

View File

@ -26,8 +26,12 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import static io.onedev.server.persistence.PersistenceUtils.*;
import static java.lang.Integer.parseInt;
import static java.lang.String.valueOf;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.io.FileUtils.writeStringToFile;
import static org.hibernate.cfg.AvailableSettings.DIALECT;
@ -51,6 +55,8 @@ public class Upgrade extends AbstractPlugin {
public static final String CHECKED_INCOMPATIBILITIES_SINCE_UPGRADED_VERSION = "incompatibilities/checked-since-upgraded-version.md";
private File upgradeDir;
protected Commandline buildCommandline(File upgradeDir, String command, String...commandArgs) {
String version = loadReleaseProps(new File(upgradeDir, RELEASE_PROPS_FILE)).getProperty("version");
@ -70,7 +76,7 @@ public class Upgrade extends AbstractPlugin {
String bootstrapClass;
if (version.startsWith("1.0-EAP")) {
int build = Integer.parseInt(StringUtils.substringAfterLast(version, "build"));
int build = parseInt(StringUtils.substringAfterLast(version, "build"));
if (build <= 26)
bootstrapClass = "com.gitplex.commons.bootstrap.Bootstrap";
else
@ -144,20 +150,32 @@ public class Upgrade extends AbstractPlugin {
return new Properties();
}
private int getDataVersion(File upgradeDir) {
AtomicInteger oldDataVersion = new AtomicInteger(0);
private int getDataVersion(File upgradeDir, int sourceAppDataVersion) {
AtomicInteger oldDataVersion = new AtomicInteger(-1);
int ret = buildCommandline(upgradeDir, "check-data-version").execute(new LineConsumer() {
buildCommandline(upgradeDir, "check-data-version").execute(new LineConsumer() {
@Override
public void consume(String line) {
String prefix = "Data version: ";
if (line.startsWith(prefix)) {
oldDataVersion.set(Integer.parseInt(line.substring(prefix.length())));
logger.info("Data version: " + oldDataVersion.get());
} else {
logger.info(prefixUpgradeTargetLog(line));
}
if (line.startsWith("Data version: ")) {
var dbDataVersion = parseInt(line.substring("Data version: ".length()));
oldDataVersion.set(dbDataVersion);
logger.info("Data version: " + dbDataVersion);
} else if (line.contains("Database is not populated yet")) {
oldDataVersion.set(0);
logger.info(prefixUpgradeTargetLog(line));
} else if (line.contains("Data version mismatch")) {
var temp = StringUtils.substringAfter(line, "db data version: ");
var dbDataVersion = parseInt(StringUtils.substringBefore(temp, ")"));
if (dbDataVersion != sourceAppDataVersion) {
logger.info(prefixUpgradeTargetLog(line));
} else {
oldDataVersion.set(dbDataVersion);
logger.info("Data version: " + dbDataVersion);
}
} else {
logger.info(prefixUpgradeTargetLog(line));
}
}
}, new LineConsumer() {
@ -167,12 +185,9 @@ public class Upgrade extends AbstractPlugin {
logger.error(prefixUpgradeTargetLog(line));
}
}).getReturnCode();
});
if (ret != 0)
return -1;
else
return oldDataVersion.get();
return oldDataVersion.get();
}
@Override
@ -185,7 +200,7 @@ public class Upgrade extends AbstractPlugin {
System.exit(1);
}
File upgradeDir = new File(Bootstrap.command.getArgs()[0]);
upgradeDir = new File(Bootstrap.command.getArgs()[0]);
if (!upgradeDir.isAbsolute() && System.getenv("WRAPPER_INIT_DIR") != null)
upgradeDir = new File(System.getenv("WRAPPER_INIT_DIR"), upgradeDir.getPath());
@ -214,21 +229,21 @@ public class Upgrade extends AbstractPlugin {
upgradeDir.getAbsolutePath());
System.exit(1);
}
Properties releaseProps = loadReleaseProps(new File(Bootstrap.installDir, RELEASE_PROPS_FILE));
Properties oldReleaseProps = loadReleaseProps(new File(upgradeDir, RELEASE_PROPS_FILE));
if (!releaseProps.equals(oldReleaseProps)) {
logger.info("Upgrading {}...", upgradeDir.getAbsolutePath());
if (OneDev.isServerRunning(upgradeDir) || OneDev.isServerRunning(Bootstrap.installDir)) {
logger.error("Please stop server before upgrading");
System.exit(1);
}
for (File file: new File(upgradeDir, "lib").listFiles()) {
if (file.getName().contains("mariadb") || file.getName().contains("mysql")
|| file.getName().contains("ojdbc") || file.getName().contains("postgresql")
for (File file : new File(upgradeDir, "lib").listFiles()) {
if (file.getName().contains("mariadb") || file.getName().contains("mysql")
|| file.getName().contains("ojdbc") || file.getName().contains("postgresql")
|| file.getName().contains("sqljdbc")) {
try {
File destDir = new File(upgradeDir, "site/lib");
@ -240,16 +255,16 @@ public class Upgrade extends AbstractPlugin {
}
}
}
File statusDir = new File(upgradeDir, "status");
if (statusDir.exists())
FileUtils.cleanDir(statusDir);
try {
if (new File(upgradeDir, "sampledb").exists()
&& !new File(upgradeDir, "internaldb").exists()) {
if (new File(upgradeDir, "sampledb").exists()
&& !new File(upgradeDir, "internaldb").exists()) {
FileUtils.moveDirectory(
new File(upgradeDir, "sampledb"),
new File(upgradeDir, "sampledb"),
new File(upgradeDir, "internaldb"));
}
@ -263,237 +278,253 @@ public class Upgrade extends AbstractPlugin {
throw new RuntimeException(e);
}
int oldDataVersion = getDataVersion(upgradeDir);
if (oldDataVersion == -1) {
int appDataVersion = parseInt(MigrationHelper.getVersion(DataMigrator.class));
int dbDataVersion = getDataVersion(upgradeDir, appDataVersion);
if (dbDataVersion <= 0) {
logger.error("Unable to upgrade specified installation due to above error");
System.exit(1);
}
int newDataVersion = Integer.parseInt(MigrationHelper.getVersion(DataMigrator.class));
if (oldDataVersion > newDataVersion) {
if (dbDataVersion > appDataVersion) {
logger.error("OneDev program is too old, please use a newer version");
System.exit(1);
}
String timestamp = DateTimeFormat.forPattern(BACKUP_DATETIME_FORMAT).print(new DateTime());
File programBackup = new File(upgradeDir, "site/program-backup/" + timestamp);
FileUtils.createDir(programBackup);
logger.info("Backing up old program files as {}...", programBackup.getAbsolutePath());
try {
for (File each: upgradeDir.listFiles()) {
if (each.isFile()) {
FileUtils.copyFileToDirectory(each, programBackup);
} else if (!each.getName().equals("temp")
&& !each.getName().equals("site")
&& !each.getName().equals("internaldb")) {
FileUtils.copyDirectoryToDirectory(each, programBackup);
var callable = new Callable<Integer>() {
@Override
public Integer call() {
String timestamp = DateTimeFormat.forPattern(BACKUP_DATETIME_FORMAT).print(new DateTime());
File programBackup = new File(upgradeDir, "site/program-backup/" + timestamp);
FileUtils.createDir(programBackup);
logger.info("Backing up old program files as {}...", programBackup.getAbsolutePath());
try {
for (File each : upgradeDir.listFiles()) {
if (each.isFile()) {
FileUtils.copyFileToDirectory(each, programBackup);
} else if (!each.getName().equals("temp")
&& !each.getName().equals("site")
&& !each.getName().equals("internaldb")) {
FileUtils.copyDirectoryToDirectory(each, programBackup);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
restoreExecutables(programBackup);
File dbBackupFile = new File(upgradeDir, "site/" + DB_BACKUP_DIR + "/" + timestamp + ".zip");
boolean isHSQL = HibernateConfig.isHSQLDialect(getDialect(upgradeDir));
boolean failed = false;
boolean dbChanged = false;
boolean dbCleaned = false;
try {
if (oldDataVersion != newDataVersion) {
logger.info("Backing up database as {}...", dbBackupFile.getAbsolutePath());
FileUtils.createDir(dbBackupFile.getParentFile());
restoreExecutables(programBackup);
int ret = buildCommandline(upgradeDir, "backup-db", dbBackupFile.getAbsolutePath()).execute(new LineConsumer() {
File dbBackupFile = new File(upgradeDir, "site/" + DB_BACKUP_DIR + "/" + timestamp + ".zip");
boolean isHSQL = HibernateConfig.isHSQLDialect(getDialect(upgradeDir));
boolean failed = false;
boolean dbChanged = false;
boolean dbCleaned = false;
try {
if (dbDataVersion != appDataVersion) {
logger.info("Backing up database as {}...", dbBackupFile.getAbsolutePath());
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
FileUtils.createDir(dbBackupFile.getParentFile());
int ret = buildCommandline(upgradeDir, "backup-db", dbBackupFile.getAbsolutePath()).execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).getReturnCode();
if (ret == 0) {
dbChanged = true;
if (isHSQL) {
FileUtils.deleteDir(new File(upgradeDir, "internaldb"), 3);
} else {
logger.info("Cleaning database with old program...");
ret = buildCommandline(upgradeDir, "clean-db").execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).getReturnCode();
}
if (ret == 0)
dbCleaned = true;
}
if (ret == 0) {
logger.info("Updating program files...");
updateProgramFiles(upgradeDir, oldDataVersion);
logger.info("Restoring database with new program...");
ret = buildCommandline(upgradeDir, "restore-db", dbBackupFile.getAbsolutePath()).execute(new LineConsumer() {
if (ret == 0) {
dbChanged = true;
if (isHSQL) {
FileUtils.deleteDir(new File(upgradeDir, "internaldb"), 3);
} else {
logger.info("Cleaning database with old program...");
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
ret = buildCommandline(upgradeDir, "clean-db").execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).getReturnCode();
}
if (ret == 0)
dbCleaned = true;
}
}).getReturnCode();
}
if (ret != 0) {
logger.error("Failed to upgrade {}", upgradeDir.getAbsolutePath());
dbCleaned = getDataVersion(upgradeDir) == -1;
failed = true;
} else {
dbCleaned = false;
}
} else {
logger.info("Copying new program files into {}...", upgradeDir.getAbsolutePath());
updateProgramFiles(upgradeDir, oldDataVersion);
}
} catch (Exception e) {
logger.error("Error upgrading " + upgradeDir.getAbsolutePath(), e);
failed = true;
}
if (failed) {
if (dbChanged && !dbCleaned) {
logger.info("Cleaning database with new program...");
try {
buildCommandline(upgradeDir, "clean-db").execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
if (ret == 0) {
logger.info("Updating program files...");
updateProgramFiles(upgradeDir, dbDataVersion);
logger.info("Restoring database with new program...");
ret = buildCommandline(upgradeDir, "restore-db", dbBackupFile.getAbsolutePath()).execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).getReturnCode();
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).checkReturnCode();
dbCleaned = true;
} catch (Exception e) {
logger.error("Error cleaning database", e);
}
}
boolean programRestored = false;
logger.info("Restoring old program files...");
try {
for (File child: programBackup.listFiles()) {
if (!child.getName().equals("site")) {
File target = new File(upgradeDir, child.getName());
if (target.isDirectory()) {
FileUtils.cleanDir(target);
FileUtils.copyDirectory(child, target);
if (ret != 0) {
logger.error("Failed to upgrade {}", upgradeDir.getAbsolutePath());
dbCleaned = getDataVersion(upgradeDir, appDataVersion) == 0;
failed = true;
} else {
FileUtils.copyFile(child, target);
dbCleaned = false;
}
} else {
logger.info("Copying new program files into {}...", upgradeDir.getAbsolutePath());
updateProgramFiles(upgradeDir, dbDataVersion);
}
} catch (Exception e) {
logger.error("Error upgrading " + upgradeDir.getAbsolutePath(), e);
failed = true;
}
if (failed) {
if (dbChanged && !dbCleaned) {
logger.info("Cleaning database with new program...");
try {
buildCommandline(upgradeDir, "clean-db").execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).checkReturnCode();
dbCleaned = true;
} catch (Exception e) {
logger.error("Error cleaning database", e);
}
}
}
if (oldDataVersion <= 102)
FileUtils.createDir(new File(upgradeDir, "site/assets/root"));
restoreExecutables(upgradeDir);
FileUtils.deleteDir(programBackup);
logger.info("Old program files restored");
programRestored = true;
} catch (Exception e) {
logger.error("Error restoring old program files", e);
logger.warn("Please restore manually from \"{}\"", programBackup.getAbsolutePath());
}
if (programRestored && dbChanged && dbCleaned) {
logger.info("Restoring old database...");
try {
buildCommandline(upgradeDir, "restore-db", dbBackupFile.getAbsolutePath(), "false").execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
boolean programRestored = false;
logger.info("Restoring old program files...");
try {
for (File child : programBackup.listFiles()) {
if (!child.getName().equals("site")) {
File target = new File(upgradeDir, child.getName());
if (target.isDirectory()) {
FileUtils.cleanDir(target);
FileUtils.copyDirectory(child, target);
} else {
FileUtils.copyFile(child, target);
}
}
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
if (dbDataVersion <= 102)
FileUtils.createDir(new File(upgradeDir, "site/assets/root"));
restoreExecutables(upgradeDir);
FileUtils.deleteDir(programBackup);
logger.info("Old program files restored");
programRestored = true;
} catch (Exception e) {
logger.error("Error restoring old program files", e);
logger.warn("Please restore manually from \"{}\"", programBackup.getAbsolutePath());
}
if (programRestored && dbChanged && dbCleaned) {
logger.info("Restoring old database...");
try {
buildCommandline(upgradeDir, "restore-db", dbBackupFile.getAbsolutePath(), "false").execute(new LineConsumer() {
@Override
public void consume(String line) {
logger.info(prefixUpgradeTargetLog(line));
}
}, new LineConsumer() {
@Override
public void consume(String line) {
logger.error(prefixUpgradeTargetLog(line));
}
}).checkReturnCode();
logger.info("Old database restored");
dbChanged = false;
} catch (Exception e) {
logger.error("Error restoring old database", e);
}
}).checkReturnCode();
logger.info("Old database restored");
dbChanged = false;
} catch (Exception e) {
logger.error("Error restoring old database", e);
}
}
logger.error("!! Failed to upgrade {}", upgradeDir.getAbsolutePath());
if (dbChanged) {
logger.warn("OneDev is unable to restore old database, please do it manually by first resetting it (delete and create), and then running below command:");
if (SystemUtils.IS_OS_WINDOWS) {
logger.info(upgradeDir.getAbsolutePath() + File.separator + "bin" + File.separator + "restore-db.bat " + dbBackupFile.getAbsolutePath());
}
logger.error("!! Failed to upgrade {}", upgradeDir.getAbsolutePath());
if (dbChanged) {
logger.warn("OneDev is unable to restore old database, please do it manually by first resetting it (delete and create), and then running below command:");
if (SystemUtils.IS_OS_WINDOWS) {
logger.info(upgradeDir.getAbsolutePath() + File.separator + "bin" + File.separator + "restore-db.bat " + dbBackupFile.getAbsolutePath());
} else {
logger.info(upgradeDir.getAbsolutePath() + File.separator + "bin" + File.separator + "restore-db.sh " + dbBackupFile.getAbsolutePath());
}
}
return 1;
} else {
logger.info(upgradeDir.getAbsolutePath() + File.separator + "bin" + File.separator + "restore-db.sh " + dbBackupFile.getAbsolutePath());
logger.info("Successfully upgraded {}", upgradeDir.getAbsolutePath());
if (dbDataVersion <= 5) {
logger.warn("\n"
+ "************************* IMPORTANT NOTICE *************************\n"
+ "* OneDev password hash algorithm has been changed for security *\n"
+ "* reason. Please reset administrator password with the *\n"
+ "* reset_admin_password command. Other users' password will be *\n"
+ "* reset and sent to their mail box automatically when they logs *\n"
+ "* into OneDev. *\n"
+ "********************************************************************");
}
FileUtils.deleteDir(programBackup);
return 0;
}
}
System.exit(1);
};
var hibernateConfig = loadHibernateConfig(upgradeDir);
int exitCode;
if (hibernateConfig.isHSQLDialect()) {
exitCode = callable.call();
} else {
logger.info("Successfully upgraded {}", upgradeDir.getAbsolutePath());
if (oldDataVersion <= 5) {
logger.warn("\n"
+ "************************* IMPORTANT NOTICE *************************\n"
+ "* OneDev password hash algorithm has been changed for security *\n"
+ "* reason. Please reset administrator password with the *\n"
+ "* reset_admin_password command. Other users' password will be *\n"
+ "* reset and sent to their mail box automatically when they logs *\n"
+ "* into OneDev. *\n"
+ "********************************************************************");
}
FileUtils.deleteDir(programBackup);
System.exit(0);
}
var classLoader = newSiteLibClassLoader(upgradeDir);
var conn = openConnection(hibernateConfig, classLoader);
exitCode = callWithDatabaseLock(conn, callable);
}
System.exit(exitCode);
} else {
logger.info("Successfully checked {}", upgradeDir.getAbsolutePath());
System.exit(0);
@ -715,11 +746,11 @@ public class Upgrade extends AbstractPlugin {
for (var buildDir: buildsDir.listFiles()) {
if (!NumberUtils.isDigits(buildDir.getName()))
continue;
var buildNumber = Integer.parseInt(buildDir.getName());
var buildNumber = parseInt(buildDir.getName());
File suffixDir = new File(buildsDir, String.format("s%03d", buildNumber%1000));
FileUtils.createDir(suffixDir);
try {
FileUtils.moveDirectory(buildDir, new File(suffixDir, String.valueOf(buildNumber)));
FileUtils.moveDirectory(buildDir, new File(suffixDir, valueOf(buildNumber)));
} catch (IOException e) {
throw new RuntimeException(e);
}

View File

@ -5270,7 +5270,13 @@ public class DataMigrator {
agentLastUsedDatesDom.writeToFile(agentLastUsedDatesFile, true);
partialAgentTokensDom.writeToFile(partialAgentTokensFile, true);
}
}
private void migrate118(File dataDir, Stack<Integer> versions) {
for (File file : dataDir.listFiles()) {
if (file.getName().startsWith("ClusterServers.xml"))
FileUtils.deleteFile(file);
}
}
}

View File

@ -1,9 +0,0 @@
package io.onedev.server.persistence;
import java.sql.Connection;
public interface ConnectionCallable<T> {
T call(Connection conn);
}

View File

@ -13,10 +13,12 @@ import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import static io.onedev.server.persistence.PersistenceUtils.callWithTransaction;
@Singleton
public class DefaultIdManager implements IdManager {
private final DataManager dataManager;
private final PersistenceManager persistenceManager;
private final ClusterManager clusterManager;
@ -25,9 +27,9 @@ public class DefaultIdManager implements IdManager {
private final Map<Class<?>, IAtomicLong> nextIds = new HashMap<>();
@Inject
public DefaultIdManager(DataManager dataManager, ClusterManager clusterManager,
SessionFactoryManager sessionFactoryManager) {
this.dataManager = dataManager;
public DefaultIdManager(PersistenceManager persistenceManager, ClusterManager clusterManager,
SessionFactoryManager sessionFactoryManager) {
this.persistenceManager = persistenceManager;
this.sessionFactoryManager = sessionFactoryManager;
this.clusterManager = clusterManager;
}
@ -36,8 +38,8 @@ public class DefaultIdManager implements IdManager {
private long getMaxId(Connection conn, Class<?> entityClass) {
try (Statement stmt = conn.createStatement()) {
String query = String.format("select max(%s) from %s",
dataManager.getColumnName(AbstractEntity.PROP_ID),
dataManager.getTableName((Class<? extends AbstractEntity>) entityClass));
persistenceManager.getColumnName(AbstractEntity.PROP_ID),
persistenceManager.getTableName((Class<? extends AbstractEntity>) entityClass));
try (ResultSet resultset = stmt.executeQuery(query)) {
if (resultset.next())
return Math.max(resultset.getLong(1), 0);
@ -51,10 +53,8 @@ public class DefaultIdManager implements IdManager {
@Override
public void init() {
dataManager.callWithConnection(new ConnectionCallable<Void>() {
@Override
public Void call(Connection conn) {
try (var conn = persistenceManager.openConnection()) {
callWithTransaction(conn, () -> {
for (var persistenceClass: sessionFactoryManager.getMetadata().getEntityBindings()) {
Class<?> entityClass = persistenceClass.getMappedClass();
var nextId = clusterManager.getHazelcastInstance().getCPSubsystem().getAtomicLong(entityClass.getName());
@ -62,9 +62,10 @@ public class DefaultIdManager implements IdManager {
nextIds.put(entityClass, nextId);
}
return null;
}
});
});
} catch (SQLException e) {
throw new RuntimeException(e);
};
}
@Override

View File

@ -69,14 +69,19 @@ import javax.validation.Validator;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.sql.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;
@Singleton
public class DefaultDataManager implements DataManager, Serializable {
import static io.onedev.server.persistence.PersistenceUtils.tableExists;
private static final Logger logger = LoggerFactory.getLogger(DefaultDataManager.class);
@Singleton
public class DefaultPersistenceManager implements PersistenceManager, Serializable {
private static final Logger logger = LoggerFactory.getLogger(DefaultPersistenceManager.class);
private static final String ENV_INITIAL_USER = "initial_user";
@ -123,12 +128,12 @@ public class DefaultDataManager implements DataManager, Serializable {
private String backupTaskId;
@Inject
public DefaultDataManager(PhysicalNamingStrategy physicalNamingStrategy, HibernateConfig hibernateConfig,
Validator validator, Dao dao, SessionFactoryManager sessionFactoryManager,
SettingManager settingManager, MailManager mailManager, TaskScheduler taskScheduler,
PasswordService passwordService, RoleManager roleManager, LinkSpecManager linkSpecManager,
EmailAddressManager emailAddressManager, UserManager userManager, ClusterManager clusterManager,
TransactionManager transactionManager) {
public DefaultPersistenceManager(PhysicalNamingStrategy physicalNamingStrategy, HibernateConfig hibernateConfig,
Validator validator, Dao dao, SessionFactoryManager sessionFactoryManager,
SettingManager settingManager, MailManager mailManager, TaskScheduler taskScheduler,
PasswordService passwordService, RoleManager roleManager, LinkSpecManager linkSpecManager,
EmailAddressManager emailAddressManager, UserManager userManager, ClusterManager clusterManager,
TransactionManager transactionManager) {
this.physicalNamingStrategy = physicalNamingStrategy;
this.hibernateConfig = hibernateConfig;
this.validator = validator;
@ -146,35 +151,7 @@ public class DefaultDataManager implements DataManager, Serializable {
this.clusterManager = clusterManager;
this.transactionManager = transactionManager;
}
@Override
public <T> T callWithConnection(ConnectionCallable<T> callable, boolean autoCommit) {
try (Connection conn = openConnection()) {
if (autoCommit) {
conn.setAutoCommit(true);
return callable.call(conn);
} else {
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
try {
T result = callable.call(conn);
conn.commit();
return result;
} catch (Exception e) {
conn.rollback();
throw ExceptionUtils.unchecked(e);
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public <T> T callWithConnection(ConnectionCallable<T> callable) {
return callWithConnection(callable, false);
}
private Metadata getMetadata() {
return sessionFactoryManager.getMetadata();
}
@ -247,24 +224,12 @@ public class DefaultDataManager implements DataManager, Serializable {
}
}
private Connection openConnection() {
try {
Driver driver = (Driver) Class.forName(hibernateConfig.getDriver(), true,
Thread.currentThread().getContextClassLoader()).getDeclaredConstructor().newInstance();
Properties connectProps = new Properties();
String user = hibernateConfig.getUser();
String password = hibernateConfig.getPassword();
if (user != null)
connectProps.put("user", user);
if (password != null)
connectProps.put("password", password);
return driver.connect(hibernateConfig.getUrl(), connectProps);
} catch (Exception e) {
throw ExceptionUtils.unchecked(e);
}
@Override
public Connection openConnection() {
return PersistenceUtils.openConnection(hibernateConfig,
Thread.currentThread().getContextClassLoader());
}
@Override
public String getTableName(Class<? extends AbstractEntity> entityClass) {
JdbcEnvironment environment = getMetadata().getDatabase()
@ -283,31 +248,10 @@ public class DefaultDataManager implements DataManager, Serializable {
private String readDbDataVersion(Connection conn) {
try {
String versionTableName = getTableName(ModelVersion.class);
boolean versionTableExists = false;
try (ResultSet resultset = conn.getMetaData().getTables(null, null, versionTableName.toUpperCase(), null)) {
if (resultset.next())
versionTableExists = true;
}
if (!versionTableExists) {
try (ResultSet resultset = conn.getMetaData().getTables(null, null, versionTableName.toLowerCase(), null)) {
if (resultset.next()) {
versionTableExists = true;
}
}
}
if (!versionTableExists) {
try (ResultSet resultset = conn.getMetaData().getTables(null, null, versionTableName, null)) {
if (resultset.next()) {
versionTableExists = true;
}
}
}
if (!versionTableExists) {
return null;
} else {
var versionTableName = getTableName(ModelVersion.class);
if (tableExists(conn, versionTableName)) {
try ( Statement stmt = conn.createStatement();
ResultSet resultset = stmt.executeQuery("select " + getColumnName(ModelVersion.PROP_VERSION_COLUMN) + " from " + versionTableName)) {
ResultSet resultset = stmt.executeQuery("select " + getColumnName(ModelVersion.PROP_VERSION_COLUMN) + " from " + versionTableName)) {
if (!resultset.next()) {
throw new RuntimeException("No data version found in database: this is normally caused "
+ "by unsuccessful restore/upgrade, please clean the database and try again");
@ -317,6 +261,8 @@ public class DefaultDataManager implements DataManager, Serializable {
throw new RuntimeException("Illegal data version format in database");
return dataVersion;
}
} else {
return null;
}
} catch (Exception e) {
if (e.getMessage() != null && e.getMessage().contains("ORA-00942"))
@ -1026,7 +972,7 @@ public class DefaultDataManager implements DataManager, Serializable {
}
public Object writeReplace() throws ObjectStreamException {
return new ManagedSerializedForm(DataManager.class);
return new ManagedSerializedForm(PersistenceManager.class);
}
}

View File

@ -1,16 +1,15 @@
package io.onedev.server.persistence;
import java.io.File;
import java.sql.Connection;
import java.util.List;
import javax.annotation.Nullable;
import io.onedev.server.model.AbstractEntity;
import io.onedev.server.model.support.administration.BackupSetting;
import io.onedev.server.util.init.ManualConfig;
public interface DataManager {
import javax.annotation.Nullable;
import java.io.File;
import java.sql.Connection;
import java.util.List;
public interface PersistenceManager {
String checkDataVersion(Connection conn, boolean allowEmptyDB);
@ -42,8 +41,6 @@ public interface DataManager {
String getColumnName(String fieldName);
<T> T callWithConnection(ConnectionCallable<T> callable, boolean autoCommit);
<T> T callWithConnection(ConnectionCallable<T> callable);
Connection openConnection();
}

View File

@ -0,0 +1,148 @@
package io.onedev.server.persistence;
import io.onedev.commons.bootstrap.Bootstrap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.Callable;
import static io.onedev.commons.utils.ExceptionUtils.unchecked;
import static io.onedev.commons.utils.FileUtils.loadProperties;
import static java.lang.String.format;
import static org.hibernate.cfg.AvailableSettings.*;
public class PersistenceUtils {
private static final Logger logger = LoggerFactory.getLogger(PersistenceUtils.class);
private static final String[] HIBERNATE_PROPS = new String[] {
DIALECT, DRIVER, URL, USER, PASS, "hibernate.hikari.leakDetectionThreshold",
"hibernate.hikari.maxLifetime", "hibernate.hikari.connectionTimeout",
"hibernate.hikari.maximumPoolSize", "hibernate.hikari.validationTimeout",
"hibernate.show_sql"
};
public static HibernateConfig loadHibernateConfig(File installDir) {
File file = new File(installDir, "conf/hibernate.properties");
HibernateConfig hibernateConfig = new HibernateConfig(loadProperties(file));
String url = hibernateConfig.getProperty(URL);
hibernateConfig.setProperty(URL,
io.onedev.commons.utils.StringUtils.replace(url, "${installDir}", installDir.getAbsolutePath()));
for (String prop: HIBERNATE_PROPS) {
String env = System.getenv(prop.replace('.', '_'));
if (env != null)
hibernateConfig.setProperty(prop, env);
}
return hibernateConfig;
}
public static Connection openConnection(HibernateConfig hibernateConfig, ClassLoader classLoader) {
try {
Driver driver = (Driver) Class.forName(hibernateConfig.getDriver(), true, classLoader).getDeclaredConstructor().newInstance();
Properties connectProps = new Properties();
String user = hibernateConfig.getUser();
String password = hibernateConfig.getPassword();
if (user != null)
connectProps.put("user", user);
if (password != null)
connectProps.put("password", password);
return driver.connect(hibernateConfig.getUrl(), connectProps);
} catch (Exception e) {
throw unchecked(e);
}
}
public static <T> T callWithTransaction(Connection conn, Callable<T> callable) {
try {
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
try {
T result = callable.call();
conn.commit();
return result;
} catch (Exception e) {
conn.rollback();
throw unchecked(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static ClassLoader newSiteLibClassLoader(File installDir) {
var siteLibs = new ArrayList<URL>();
for (var file: new File(installDir, "site/lib").listFiles()) {
if (file.getName().endsWith(".jar")) {
try {
siteLibs.add(file.toURI().toURL());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
return new URLClassLoader(siteLibs.toArray(new URL[0]),
PersistenceUtils.class.getClassLoader());
}
public static boolean tableExists(Connection conn, String tableName) {
try {
var metadata = conn.getMetaData();
try (ResultSet resultset = metadata.getTables(null, null, tableName, null)) {
if (resultset.next())
return true;
}
try (ResultSet resultset = metadata.getTables(null, null, tableName.toUpperCase(), null)) {
if (resultset.next())
return true;
}
try (ResultSet resultset = metadata.getTables(null, null, tableName.toLowerCase(), null)) {
if (resultset.next())
return true;
}
return false;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static <T> T callWithDatabaseLock(Connection conn, Callable<T> callable) {
var lockTableName = "o_DatabaseLock";
callWithTransaction(conn, () -> {
try (var stmt = conn.createStatement()) {
stmt.executeQuery(format("select * from o_ModelVersion for update"));
}
if (!tableExists(conn, lockTableName)) {
try (var stmt = conn.createStatement()) {
stmt.execute(format("create table %s (o_id int)", lockTableName));
stmt.executeUpdate(format("insert into %s values(1)", lockTableName));
}
}
return null;
});
return callWithTransaction(conn, () -> {
while (true) {
try (var stmt = conn.createStatement()) {
stmt.executeQuery(format("select * from %s for update", lockTableName));
break;
} catch (Exception e) {
Thread.sleep(1000);
}
}
return callable.call();
});
}
}

View File

@ -71,22 +71,22 @@ public abstract class ReviewListPanel extends Panel {
protected void onInitialize() {
super.onInitialize();
add(new ListView<PullRequestReview>("reviews", reviewsModel) {
add(new ListView<>("reviews", reviewsModel) {
@Override
protected void populateItem(ListItem<PullRequestReview> item) {
PullRequestReview review = item.getModelObject();
item.add(new UserIdentPanel("user", review.getUser(), Mode.AVATAR_AND_NAME));
PullRequest request = getPullRequest();
item.add(new ReviewStatusIcon("status", false) {
@Override
protected Status getStatus() {
return item.getModelObject().getStatus();
}
}.setVisible(!request.isNew()));
item.add(new AjaxLink<Void>("refresh") {
@ -94,35 +94,35 @@ public abstract class ReviewListPanel extends Panel {
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
PullRequestReview review = item.getModelObject();
if (!review.getUser().equals(SecurityUtils.getUser())) {
attributes.getAjaxCallListeners().add(new ConfirmClickListener("Do you really want to "
+ "request another review from '" + review.getUser().getDisplayName() + "'?"));
}
}
@Override
public void onClick(AjaxRequestTarget target) {
PullRequestReview review = item.getModelObject();
review.setStatus(Status.PENDING);
OneDev.getInstance(PullRequestReviewManager.class).update(review);
}
@Override
protected void onConfigure() {
super.onConfigure();
PullRequestReview review = item.getModelObject();
User currentUser = SecurityUtils.getUser();
setVisible(!request.isNew()
setVisible(!request.isNew()
&& !request.isMerged()
&& review.getStatus() != PullRequestReview.Status.PENDING
&& review.getStatus() != PullRequestReview.Status.PENDING
&& (SecurityUtils.canModify(getPullRequest()) || review.getUser().equals(currentUser)));
}
});
item.add(new AjaxLink<Void>("delete") {
@Override
@ -133,7 +133,7 @@ public abstract class ReviewListPanel extends Panel {
+ "remove reviewer '" + item.getModelObject().getUser().getDisplayName() + "'?"));
}
}
@Override
public void onClick(AjaxRequestTarget target) {
PullRequest request = getPullRequest();
@ -146,10 +146,10 @@ public abstract class ReviewListPanel extends Panel {
if (request.getReview(reviewer).getStatus() != Status.EXCLUDED)
reviewerRequired = true;
} else if (request.getReview(reviewer).getStatus() == Status.EXCLUDED) {
PullRequestReviewManager reviewManager =
PullRequestReviewManager reviewManager =
OneDev.getInstance(PullRequestReviewManager.class);
reviewManager.update(review);
for (PullRequestReview eachReview: request.getReviews()) {
for (PullRequestReview eachReview : request.getReviews()) {
if (eachReview.isNew())
reviewManager.create(eachReview);
}
@ -157,25 +157,25 @@ public abstract class ReviewListPanel extends Panel {
reviewerRequired = true;
}
if (reviewerRequired) {
getSession().warn("Reviewer '" + reviewer.getDisplayName()
getSession().warn("Reviewer '" + reviewer.getDisplayName()
+ "' is required and can not be removed");
} else if (request.isNew()) {
target.add(ReviewListPanel.this);
}
reviewsModel.detach();
}
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(SecurityUtils.canModify(getPullRequest()) && !request.isMerged());
}
});
}
});
add(new ReviewerChoice("addReviewer") {

View File

@ -55,6 +55,7 @@ public abstract class ReviewerChoice extends SelectToAddChoice<User> {
review = new PullRequestReview();
review.setRequest(getPullRequest());
review.setUser(user);
getPullRequest().getReviews().add(review);
} else {
review.setStatus(Status.PENDING);
}
@ -64,8 +65,6 @@ public abstract class ReviewerChoice extends SelectToAddChoice<User> {
OneDev.getInstance(PullRequestReviewManager.class).create(review);
else
OneDev.getInstance(PullRequestReviewManager.class).update(review);
} else {
getPullRequest().getReviews().add(review);
}
};

View File

@ -4,7 +4,7 @@ import io.onedev.commons.utils.FileUtils;
import io.onedev.server.OneDev;
import io.onedev.server.cluster.ClusterManager;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.persistence.DataManager;
import io.onedev.server.persistence.PersistenceManager;
import io.onedev.server.web.editable.BeanContext;
import io.onedev.server.web.page.admin.AdministrationPage;
import org.apache.tika.mime.MimeTypes;
@ -75,7 +75,7 @@ public class DatabaseBackupPage extends AdministrationPage {
public void writeData(Attributes attributes) throws IOException {
File tempDir = FileUtils.createTempDir("backup");
try {
DataManager databaseManager = OneDev.getInstance(DataManager.class);
PersistenceManager databaseManager = OneDev.getInstance(PersistenceManager.class);
databaseManager.exportData(tempDir);
FileUtils.zip(tempDir, attributes.getResponse().getOutputStream());
} finally {

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<build>
<resources>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.authenticator.ldap.LdapModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.buildspec.gradle.GradleModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.buildspec.maven.MavenModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.buildspec.node.NodePluginModule</moduleClass>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.executor.kubernetes.KubernetesModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.executor.serverdocker.ServerDockerModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.executor.servershell.ServerShellModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.bitbucketcloud.BitbucketModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.gitea.GiteaModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.github.GitHubModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.gitlab.GitLabModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.jiracloud.JiraModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.url.UrlModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.imports.youtrack.YouTrackModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.notification.discord.DiscordModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.notification.slack.SlackModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.report.coverage.CoverageModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.report.markdown.MarkdownModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.report.problem.ProblemModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.report.unittest.UnitTestModule</moduleClass>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.sso.discord.DiscordModule</moduleClass>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.sso.openid.OpenIdModule</moduleClass>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server</artifactId>
<version>8.1.1</version>
<version>8.1.2</version>
</parent>
<dependencies>
<dependency>

View File

@ -1,10 +1,6 @@
package io.onedev.server.product;
import io.onedev.commons.bootstrap.Bootstrap;
import io.onedev.commons.loader.AbstractPluginModule;
import io.onedev.commons.utils.FileUtils;
import io.onedev.commons.utils.StringUtils;
import io.onedev.server.OneDev;
import io.onedev.server.ServerConfig;
import io.onedev.server.jetty.ServerConfigurator;
import io.onedev.server.jetty.ServletConfigurator;
@ -15,37 +11,21 @@ import java.io.File;
import java.util.HashSet;
import java.util.Set;
import static org.hibernate.cfg.AvailableSettings.*;
import static io.onedev.commons.bootstrap.Bootstrap.installDir;
import static io.onedev.commons.utils.FileUtils.loadProperties;
import static io.onedev.server.OneDev.getAssetsDir;
import static io.onedev.server.persistence.PersistenceUtils.loadHibernateConfig;
public class ProductModule extends AbstractPluginModule {
private static final String[] HIBERNATE_PROPS = new String[] {
DIALECT, DRIVER, URL, USER, PASS, "hibernate.hikari.leakDetectionThreshold",
"hibernate.hikari.maxLifetime", "hibernate.hikari.connectionTimeout",
"hibernate.hikari.maximumPoolSize", "hibernate.hikari.validationTimeout",
"hibernate.show_sql"
};
@Override
protected void configure() {
super.configure();
File file = new File(Bootstrap.installDir, "conf/hibernate.properties");
HibernateConfig hibernateConfig = new HibernateConfig(FileUtils.loadProperties(file));
String url = hibernateConfig.getProperty(URL);
hibernateConfig.setProperty(URL,
StringUtils.replace(url, "${installDir}", Bootstrap.installDir.getAbsolutePath()));
bind(HibernateConfig.class).toInstance(loadHibernateConfig(installDir));
for (String prop: HIBERNATE_PROPS) {
String env = System.getenv(prop.replace('.', '_'));
if (env != null)
hibernateConfig.setProperty(prop, env);
}
bind(HibernateConfig.class).toInstance(hibernateConfig);
file = new File(Bootstrap.installDir, "conf/server.properties");
ServerProperties serverProps = new ServerProperties(FileUtils.loadProperties(file));
var file = new File(installDir, "conf/server.properties");
ServerProperties serverProps = new ServerProperties(loadProperties(file));
bind(ServerProperties.class).toInstance(serverProps);
bind(ServerConfig.class).to(DefaultServerConfig.class);
@ -55,7 +35,7 @@ public class ProductModule extends AbstractPluginModule {
contribute(ProjectNameReservation.class, () -> {
Set<String> reserved = new HashSet<>();
for (var file1 : OneDev.getAssetsDir().listFiles())
for (var file1 : getAssetsDir().listFiles())
reserved.add(file1.getName());
return reserved;
});