mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Fix issue #1344 - Reviewer appears duplicated
This commit is contained in:
parent
7c90f0388c
commit
1ff550d53f
2
pom.xml
2
pom.xml
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
package io.onedev.server.persistence;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
public interface ConnectionCallable<T> {
|
||||
|
||||
T call(Connection conn);
|
||||
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
|
||||
}
|
||||
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -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") {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user