diff --git a/server-core/src/main/java/io/onedev/server/maintenance/Upgrade.java b/server-core/src/main/java/io/onedev/server/maintenance/Upgrade.java index 8c151ca6e9..6f35c3f56b 100644 --- a/server-core/src/main/java/io/onedev/server/maintenance/Upgrade.java +++ b/server-core/src/main/java/io/onedev/server/maintenance/Upgrade.java @@ -50,6 +50,10 @@ public class Upgrade extends DefaultPersistManager { private static final Pattern PRODUCT_FILE_NAME_PATTERN = Pattern.compile("io\\.onedev\\.server-product-(.*?)\\.jar"); + public static final String FILE_INCOMPATIBILITIES = "incompatibilities.md"; + + public static final String FILE_INCOMPATIBILITIES_SINCE_UPGRADED_VERSION = "incompatibilities-since-upgraded-version.md"; + @Inject public Upgrade(PhysicalNamingStrategy physicalNamingStrategy, HibernateProperties properties, Interceptor interceptor, @@ -585,6 +589,24 @@ public class Upgrade extends DefaultPersistManager { FileUtils.copyFile(new File(Bootstrap.installDir, "license.txt"), new File(upgradeDir, "license.txt")); FileUtils.copyFile(new File(Bootstrap.installDir, "version.txt"), new File(upgradeDir, "version.txt")); FileUtils.copyFile(new File(Bootstrap.installDir, "build.txt"), new File(upgradeDir, "build.txt")); + + String incompatibilities = FileUtils.readFileToString( + new File(Bootstrap.installDir, FILE_INCOMPATIBILITIES), StandardCharsets.UTF_8); + if (new File(upgradeDir, FILE_INCOMPATIBILITIES).exists()) { + String incompatibilitiesOfUpgradedVersion = FileUtils.readFileToString( + new File(upgradeDir, FILE_INCOMPATIBILITIES), StandardCharsets.UTF_8); + if (incompatibilities.startsWith(incompatibilitiesOfUpgradedVersion)) { + String incompatibilitiesSinceUpgradedVersion = + incompatibilities.substring(incompatibilitiesOfUpgradedVersion.length()); + if (StringUtils.isNotBlank(incompatibilitiesSinceUpgradedVersion)) { + FileUtils.writeFile( + new File(upgradeDir, FILE_INCOMPATIBILITIES_SINCE_UPGRADED_VERSION), + incompatibilitiesSinceUpgradedVersion); + } + } + } + FileUtils.copyFile(new File(Bootstrap.installDir, FILE_INCOMPATIBILITIES), + new File(upgradeDir, FILE_INCOMPATIBILITIES)); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/server-core/src/main/java/io/onedev/server/web/OneUrlMapper.java b/server-core/src/main/java/io/onedev/server/web/OneUrlMapper.java index 679d37958c..45590ff6bd 100644 --- a/server-core/src/main/java/io/onedev/server/web/OneUrlMapper.java +++ b/server-core/src/main/java/io/onedev/server/web/OneUrlMapper.java @@ -56,6 +56,7 @@ import io.onedev.server.web.page.admin.user.password.UserPasswordPage; import io.onedev.server.web.page.admin.user.profile.UserProfilePage; import io.onedev.server.web.page.admin.user.ssh.UserSshKeysPage; import io.onedev.server.web.page.builds.BuildListPage; +import io.onedev.server.web.page.help.IncompatibilitiesPage; import io.onedev.server.web.page.help.MethodDetailPage; import io.onedev.server.web.page.help.ResourceDetailPage; import io.onedev.server.web.page.help.ResourceListPage; @@ -161,6 +162,7 @@ public class OneUrlMapper extends CompoundRequestMapper { } private void addHelpPages() { + add(new DynamicPathPageMapper("help/incompatibilities", IncompatibilitiesPage.class)); add(new DynamicPathPageMapper("help/api", ResourceListPage.class)); add(new DynamicPathPageMapper("help/api/${resource}", ResourceDetailPage.class)); add(new DynamicPathPageMapper("help/api/${resource}/${method}", MethodDetailPage.class)); diff --git a/server-core/src/main/java/io/onedev/server/web/page/base/BasePage.java b/server-core/src/main/java/io/onedev/server/web/page/base/BasePage.java index 026aa6ead8..82e35c4cd6 100644 --- a/server-core/src/main/java/io/onedev/server/web/page/base/BasePage.java +++ b/server-core/src/main/java/io/onedev/server/web/page/base/BasePage.java @@ -2,6 +2,7 @@ package io.onedev.server.web.page.base; import static org.apache.wicket.ajax.attributes.CallbackParameter.explicit; +import java.io.File; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; @@ -45,8 +46,10 @@ import org.unbescape.javascript.JavaScriptEscape; import com.google.common.base.Splitter; +import io.onedev.commons.bootstrap.Bootstrap; import io.onedev.commons.loader.AppLoader; import io.onedev.server.OneDev; +import io.onedev.server.maintenance.Upgrade; import io.onedev.server.model.User; import io.onedev.server.security.SecurityUtils; import io.onedev.server.util.CryptoUtils; @@ -56,6 +59,7 @@ import io.onedev.server.web.behavior.ForceOrdinaryStyleBehavior; import io.onedev.server.web.behavior.WebSocketObserver; import io.onedev.server.web.component.svg.SpriteImage; import io.onedev.server.web.editable.BeanEditor; +import io.onedev.server.web.page.help.IncompatibilitiesPage; import io.onedev.server.web.page.simple.SimplePage; import io.onedev.server.web.page.simple.security.LoginPage; import io.onedev.server.web.page.simple.serverinit.ServerInitPage; @@ -80,6 +84,12 @@ public abstract class BasePage extends WebPage { if (!isPermitted()) unauthorized(); + if (SecurityUtils.isAdministrator() + && !(getPage() instanceof IncompatibilitiesPage) + && new File(Bootstrap.installDir, Upgrade.FILE_INCOMPATIBILITIES_SINCE_UPGRADED_VERSION).exists()) { + throw new RestartResponseAtInterceptPageException(IncompatibilitiesPage.class); + } + AbstractPostAjaxBehavior popStateBehavior; add(popStateBehavior = new AbstractPostAjaxBehavior() { diff --git a/server-core/src/main/java/io/onedev/server/web/page/help/IncompatibilitiesPage.html b/server-core/src/main/java/io/onedev/server/web/page/help/IncompatibilitiesPage.html new file mode 100644 index 0000000000..0278f089c8 --- /dev/null +++ b/server-core/src/main/java/io/onedev/server/web/page/help/IncompatibilitiesPage.html @@ -0,0 +1,18 @@ + + + + + There are incompatibilities since your upgraded version. + + + + + Go Back + + you may show this page later via incompatibilities link in help menu + + + + + + \ No newline at end of file diff --git a/server-core/src/main/java/io/onedev/server/web/page/help/IncompatibilitiesPage.java b/server-core/src/main/java/io/onedev/server/web/page/help/IncompatibilitiesPage.java new file mode 100644 index 0000000000..55daa2e77e --- /dev/null +++ b/server-core/src/main/java/io/onedev/server/web/page/help/IncompatibilitiesPage.java @@ -0,0 +1,112 @@ +package io.onedev.server.web.page.help; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.wicket.Component; +import org.apache.wicket.RestartResponseAtInterceptPageException; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.link.Link; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LoadableDetachableModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import io.onedev.commons.bootstrap.Bootstrap; +import io.onedev.commons.utils.FileUtils; +import io.onedev.server.maintenance.Upgrade; +import io.onedev.server.web.component.markdown.MarkdownViewer; +import io.onedev.server.web.page.layout.LayoutPage; + +@SuppressWarnings("serial") +public class IncompatibilitiesPage extends LayoutPage { + + private final IModel incompatibilitiesSinceUpgradedVersionModel = new LoadableDetachableModel() { + + @Override + protected String load() { + File incompatibilitiesSinceUpgradedVersionFile = + new File(Bootstrap.installDir, Upgrade.FILE_INCOMPATIBILITIES_SINCE_UPGRADED_VERSION); + if (incompatibilitiesSinceUpgradedVersionFile.exists()) { + try { + String incompatibilitiesSinceUpgradedVersion = FileUtils.readFileToString( + incompatibilitiesSinceUpgradedVersionFile, StandardCharsets.UTF_8); + FileUtils.deleteFile(incompatibilitiesSinceUpgradedVersionFile); + return incompatibilitiesSinceUpgradedVersion; + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + return null; + } + } + + }; + + public IncompatibilitiesPage(PageParameters params) { + super(params); + } + + @Override + protected void onDetach() { + incompatibilitiesSinceUpgradedVersionModel.detach(); + super.onDetach(); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + add(new WebMarkupContainer("warning") { + + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(incompatibilitiesSinceUpgradedVersionModel.getObject() != null); + } + + }); + + add(new MarkdownViewer("incompatibilities", new LoadableDetachableModel() { + + @Override + protected String load() { + try { + if (incompatibilitiesSinceUpgradedVersionModel.getObject() != null) { + return incompatibilitiesSinceUpgradedVersionModel.getObject(); + } else { + return FileUtils.readFileToString( + new File(Bootstrap.installDir, Upgrade.FILE_INCOMPATIBILITIES), + StandardCharsets.UTF_8); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + }, null)); + + add(new Link("back") { + + @Override + public void onClick() { + continueToOriginalDestination(); + } + + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(RestartResponseAtInterceptPageException.getOriginalUrl() != null); + } + + }); + + } + + @Override + protected Component newTopbarTitle(String componentId) { + return new Label(componentId, "Incompatibilities"); + } + +} diff --git a/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.html b/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.html index 1314449f3e..73591d47c4 100644 --- a/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.html +++ b/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.html @@ -24,7 +24,7 @@ Documentation Support & Bug Report RESTful API - Incompatibilities + Incompatibilities diff --git a/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.java b/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.java index dc839f4925..e0fa43991c 100644 --- a/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.java +++ b/server-core/src/main/java/io/onedev/server/web/page/layout/LayoutPage.java @@ -1,15 +1,11 @@ package io.onedev.server.web.page.layout; -import java.io.File; -import java.io.IOException; import java.io.Serializable; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import javax.servlet.http.Cookie; -import org.apache.commons.io.FileUtils; import org.apache.shiro.subject.PrincipalCollection; import org.apache.wicket.Component; import org.apache.wicket.RestartResponseAtInterceptPageException; @@ -36,7 +32,6 @@ import org.apache.wicket.request.mapper.parameter.PageParameters; import com.google.common.collect.Lists; -import io.onedev.commons.bootstrap.Bootstrap; import io.onedev.commons.loader.AppLoader; import io.onedev.commons.loader.Plugin; import io.onedev.server.OneDev; @@ -83,6 +78,7 @@ import io.onedev.server.web.page.admin.user.UserListPage; import io.onedev.server.web.page.admin.user.UserPage; import io.onedev.server.web.page.admin.user.create.NewUserPage; import io.onedev.server.web.page.base.BasePage; +import io.onedev.server.web.page.help.IncompatibilitiesPage; import io.onedev.server.web.page.my.MyPage; import io.onedev.server.web.page.my.accesstoken.MyAccessTokenPage; import io.onedev.server.web.page.my.avatar.MyAvatarPage; @@ -306,20 +302,7 @@ public abstract class LayoutPage extends BasePage { Plugin product = AppLoader.getProduct(); sidebar.add(new Label("productVersion", "Ver. " + product.getVersion())); sidebar.add(new ExternalLink("docLink", OneDev.getInstance().getDocRoot() + "/")); - try { - String buildNumber = FileUtils.readFileToString( - new File(Bootstrap.installDir, "build.txt"), - StandardCharsets.UTF_8); - if (buildNumber.length() != 0) { - sidebar.add(new ExternalLink("incompatibilities", - "https://code.onedev.io/projects/160/builds/" + buildNumber.trim() - + "/markdown/Incompatibilities/doc/incompatibilities.md")); - } else { - sidebar.add(new WebMarkupContainer("incompatibilities").setVisible(false)); - } - } catch (IOException e) { - throw new RuntimeException(e); - } + sidebar.add(new BookmarkablePageLink("incompatibilities", IncompatibilitiesPage.class)); WebMarkupContainer topbar = new WebMarkupContainer("topbar"); add(topbar); diff --git a/doc/incompatibilities.md b/server-product/system/incompatibilities.md similarity index 94% rename from doc/incompatibilities.md rename to server-product/system/incompatibilities.md index a16030df1b..d897e76c26 100644 --- a/doc/incompatibilities.md +++ b/server-product/system/incompatibilities.md @@ -50,7 +50,7 @@ consideration. As a result of this, password authentication specified previously 1. Submodule authentication - You will need to use custom http/ssh clone credential with permission to access submodule projects to retrieve source. Refer to [usage scenario](https://code.onedev.io/projects/onedev-manual/blob/master/pages/clone-submodules-via-ssh.md) for an example. + You will need to use custom http/ssh clone credential with permission to access submodule projects to retrieve source. Refer to [usage scenario](https://code.onedev.io/projects/162/blob/main/pages/clone-submodules-via-ssh.md) for an example. 2. Project dependency authentication
+ you may show this page later via incompatibilities link in help menu +